From 2896b9700d2f7480bf4bf3a9aceb399df5e93963 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Wed, 1 Jun 2016 15:44:47 +0200 Subject: [PATCH 01/16] Add proper policy setup for privacy-related privileges Thanks to privielge-checker module API we can setup "ASK-USER"/popup Cynara policy for privacy-related privileges. Test with https://review.tizen.org/gerrit/#/c/72604/ Change-Id: I6bb8bc1dffc1e607c09b7722c6fac33b29620b4e --- packaging/security-manager.spec | 1 + src/common/CMakeLists.txt | 1 + src/common/config.cpp | 2 + src/common/cynara.cpp | 118 ++++++++++++++++++++++++++++---------- src/common/include/config.h | 5 +- src/common/include/cynara.h | 12 ++-- src/common/include/service_impl.h | 2 + src/common/service_impl.cpp | 24 ++++++-- 8 files changed, 125 insertions(+), 40 deletions(-) diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec index 7ac305c..20a84bd 100644 --- a/packaging/security-manager.spec +++ b/packaging/security-manager.spec @@ -25,6 +25,7 @@ BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(db-util) BuildRequires: pkgconfig(cynara-admin) BuildRequires: pkgconfig(cynara-client-async) +BuildRequires: pkgconfig(security-privilege-manager) BuildRequires: boost-devel %{?systemd_requires} diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index fcfb46b..7c10f7b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -9,6 +9,7 @@ PKG_CHECK_MODULES(COMMON_DEP cynara-admin cynara-client-async libtzplatform-config + security-privilege-manager ) IF(DPL_WITH_DLOG) diff --git a/src/common/config.cpp b/src/common/config.cpp index 6b1887d..8c8dd9e 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -45,6 +45,8 @@ const std::string PRIVILEGE_APPSHARING_ADMIN = "http://tizen.org/privilege/notex const std::string APPS_NAME_FILE = "apps-names"; const std::string SKEL_DIR = "/etc/skel"; + +const std::string PRIVACY_POLICY_DESC = "Ask user"; }; } /* namespace SecurityManager */ diff --git a/src/common/cynara.cpp b/src/common/cynara.cpp index d08f7d4..d2c26d2 100644 --- a/src/common/cynara.cpp +++ b/src/common/cynara.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -27,6 +27,7 @@ #include #include +#include namespace SecurityManager { @@ -113,7 +114,6 @@ CynaraAdmin::BucketsMap CynaraAdmin::Buckets = { Bucket::MANIFESTS, std::string("MANIFESTS")}, }; - CynaraAdminPolicy::CynaraAdminPolicy(const std::string &client, const std::string &user, const std::string &privilege, int operation, const std::string &bucket) @@ -288,37 +288,74 @@ void CynaraAdmin::SetPolicies(const std::vector &policies) void CynaraAdmin::UpdateAppPolicy( const std::string &label, const std::string &user, - const std::vector &privileges) -{ - std::unordered_set privilegesSet(privileges.begin(), privileges.end()); - - std::vector policies; - CynaraAdmin::getInstance().ListPolicies( - CynaraAdmin::Buckets.at(Bucket::MANIFESTS), - label, user, CYNARA_ADMIN_ANY, policies); + const std::vector &privileges, + std::function isPrivacy) +{ + auto calcPolicies = [&label]( + const std::string &user, + const std::vector &privileges, + const std::string &bucket, + int policyToSet, + std::vector &policies) + { + std::vector oldPolicies; + std::unordered_set privilegesSet(privileges.begin(), + privileges.end()); + CynaraAdmin::getInstance().ListPolicies(bucket, label, user, + CYNARA_ADMIN_ANY, oldPolicies); + + // Compare previous policies with set of new requested privileges + for (auto &policy : oldPolicies) { + if (privilegesSet.erase(policy.privilege)) { + // privilege was found and removed from the set, keeping policy + LogDebug("(user = " << user << " label = " << label << ") " << + "keeping privilege " << policy.privilege); + } else { + // privilege was not found in the set, deleting policy + policy.result = static_cast(CynaraAdminPolicy::Operation::Delete); + LogDebug("(user = " << user << " label = " << label << ") " << + "removing privilege " << policy.privilege); + } + policies.push_back(std::move(policy)); + } - // Compare previous policies with set of new requested privileges - for (auto &policy : policies) { - if (privilegesSet.erase(policy.privilege)) { - // privilege was found and removed from the set, keeping policy - LogDebug("(user = " << user << " label = " << label << ") " << - "keeping privilege " << policy.privilege); - } else { - // privilege was not found in the set, deleting policy - policy.result = static_cast(CynaraAdminPolicy::Operation::Delete); + // Add policies for privileges that weren't previously enabled + // Those that were previously enabled are now removed from privilegesSet + for (const auto &privilege : privilegesSet) { LogDebug("(user = " << user << " label = " << label << ") " << - "removing privilege " << policy.privilege); + "adding privilege " << privilege); + policies.push_back(CynaraAdminPolicy(label, user, privilege, policyToSet, bucket)); } - } + }; - // Add policies for privileges that weren't previously enabled - // Those that were previously enabled are now removed from privilegesSet - for (const auto &privilege : privilegesSet) { - LogDebug("(user = " << user << " label = " << label << ") " << - "adding privilege " << privilege); - policies.push_back(CynaraAdminPolicy(label, user, privilege, - static_cast(CynaraAdminPolicy::Operation::Allow), - Buckets.at(Bucket::MANIFESTS))); + std::vector policies; + + // 1st, performing operation on MANIFESTS bucket + calcPolicies(user, privileges, Buckets.at(Bucket::MANIFESTS), + static_cast(CynaraAdminPolicy::Operation::Allow), + policies); + + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + + std::vector privacyPrivileges; + for (auto &p : privileges) + if (isPrivacy(p)) + privacyPrivileges.push_back(p); + + // 2nd, performing operation on PRIVACY_MANAGER bucket for all affected users + if (user == CYNARA_ADMIN_WILDCARD) { + // perform bucket setting for all users in the system, app is installed for everyone + std::vector users; + ListUsers(users); + for (uid_t id : users) { + calcPolicies(std::to_string(id), privacyPrivileges, + Buckets.at(Bucket::PRIVACY_MANAGER), + askUserPolicy, policies); + } + } else { + // local single user installation, do it only for that particular user + calcPolicies(user, privacyPrivileges, Buckets.at(Bucket::PRIVACY_MANAGER), + askUserPolicy, policies); } SetPolicies(policies); @@ -339,10 +376,12 @@ void CynaraAdmin::GetAppPolicy(const std::string &label, const std::string &user } } -void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType) +void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType, + std::function isPrivacy) { Bucket bucket; std::vector policies; + std::string userStr = std::to_string(uid); switch (userType) { case SM_USER_TYPE_SYSTEM: @@ -365,11 +404,28 @@ void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType) } policies.push_back(CynaraAdminPolicy(CYNARA_ADMIN_WILDCARD, - std::to_string(static_cast(uid)), + userStr, CYNARA_ADMIN_WILDCARD, Buckets.at(bucket), Buckets.at(Bucket::MAIN))); + // for each global app: retrieve its privacy-related privileges and set + // their policy in PRIVACY_MANAGER bucket to "Ask user" + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + + std::vector appPolicies; + CynaraAdmin::getInstance().ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS), + CYNARA_ADMIN_ANY, CYNARA_ADMIN_WILDCARD, + CYNARA_ADMIN_ANY, appPolicies); + + for (CynaraAdminPolicy &policy : appPolicies) + if (isPrivacy(policy.privilege)) + policies.push_back(CynaraAdminPolicy(policy.client, + userStr, + policy.privilege, + askUserPolicy, + Buckets.at(Bucket::PRIVACY_MANAGER))); + CynaraAdmin::getInstance().SetPolicies(policies); } diff --git a/src/common/include/config.h b/src/common/include/config.h index 9f4c466..01d0f79 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -41,10 +41,13 @@ extern const std::string PRIVILEGE_POLICY_USER; extern const std::string PRIVILEGE_POLICY_ADMIN; extern const std::string PRIVILEGE_APPSHARING_ADMIN; -/* Files used in permitted label managment*/ +/* Files used in permitted label managment */ extern const std::string APPS_NAME_FILE; extern const std::string SKEL_DIR; + +/* Ask-user policy description */ +extern const std::string PRIVACY_POLICY_DESC; }; } /* namespace SecurityManager */ diff --git a/src/common/include/cynara.h b/src/common/include/cynara.h index 219667d..1d267d4 100644 --- a/src/common/include/cynara.h +++ b/src/common/include/cynara.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -126,10 +127,11 @@ public: * @param label application Smack label * @param user user identifier * @param privileges currently enabled privileges - * + * @param isPrivacy a function that checks if privilege is privacy-related */ void UpdateAppPolicy(const std::string &label, const std::string &user, - const std::vector &privileges); + const std::vector &privileges, + std::function isPrivacy); /** * Fetch Cynara policies for the application and the user. @@ -150,8 +152,10 @@ public: * * @param uid new user uid * @param userType type as enumerated in security-manager.h + * @param isPrivacy a function that checks if privilege is privacy-related */ - void UserInit(uid_t uid, security_manager_user_type userType); + void UserInit(uid_t uid, security_manager_user_type userType, + std::function isPrivacy); /** * List all users registered in Cynara diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index fbe6c5b..652244a 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -72,6 +72,8 @@ private: static void getTizen2XApps(SmackRules::PkgsApps &pkgsApps); + static bool isPrivilegePrivacy(const std::string &privilege); + int dropOnePrivateSharing(const std::string &ownerAppName, const std::string &ownerPkgName, const std::vector &ownerPkgContents, diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index b8ffc8a..583d23f 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -35,6 +35,8 @@ #include #include +#include + #include #include "protocols.h" #include "privilege_db.h" @@ -398,6 +400,19 @@ void ServiceImpl::getTizen2XApps(SmackRules::PkgsApps &pkgsApps) } } +bool ServiceImpl::isPrivilegePrivacy(const std::string &privilege) +{ + int ret = privilege_info_is_privacy(privilege.c_str()); + if (ret == 1) + return true; + if (ret != 0) + LogError("privilege_info_is_privacy called with " << privilege << " returned error: " << ret); + // FIXME: we should probably disallow such installation where privilege is not known + // However, currently privielge-checker seems to return -1 with so many real privileges + // that it would make ask-user testing impossible. + return false; +} + int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req) { std::vector addedPermissions; @@ -442,8 +457,7 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req) /* Get all application ids in the package to generate rules withing the package */ PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents); PrivilegeDb::getInstance().GetPkgAuthorId(req.pkgName, authorId); - CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges); - + CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges, isPrivilegePrivacy); // if app is targetted to Tizen 2.X, give other 2.X apps RO rules to it's shared dir if (isTizen2XVersion(req.tizenVersion)) getTizen2XApps(tizen2XpkgsApps); @@ -563,7 +577,8 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) if (isTizen2XVersion(req.tizenVersion)) getTizen2XApps(tizen2XpkgsApps); - CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector()); + CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector(), isPrivilegePrivacy); + PrivilegeDb::getInstance().CommitTransaction(); LogDebug("Application uninstallation commited to database"); PermissibleSet::updatePermissibleFile(req.uid, req.installationType); @@ -713,7 +728,8 @@ int ServiceImpl::userAdd(const Credentials &creds, uid_t uidAdded, int userType) } try { - CynaraAdmin::getInstance().UserInit(uidAdded, static_cast(userType)); + CynaraAdmin::getInstance().UserInit(uidAdded, static_cast(userType), isPrivilegePrivacy); + } catch (CynaraException::InvalidParam &e) { return SECURITY_MANAGER_ERROR_INPUT_PARAM; } -- 2.7.4 From 21dc464d6d5a953b89f02c0e7e8d3673ede8f9e1 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Fri, 3 Jun 2016 14:04:19 +0200 Subject: [PATCH 02/16] Fix policy access control for accessing another user's policy Test with: https://review.tizen.org/gerrit/#/c/73009/ Change-Id: I8eb503d6a2ffb21afecf65206fdef28458734283 --- src/common/service_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 583d23f..40bf386 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -876,8 +876,8 @@ int ServiceImpl::getConfiguredPolicy(const Credentials &creds, bool forAdmin, if (uidStr.compare(user)) { if (!authenticate(creds, Config::PRIVILEGE_POLICY_ADMIN)) { - LogWarning("Not enough privilege to access other user's personal policies. Limiting query to personal privileges."); - user = uidStr; + LogWarning("Not enough privilege to access other user's personal policies"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; }; }; //Fetch privileges from PRIVACY_MANAGER bucket -- 2.7.4 From 77d45878ff4d28863b88c5f45a2f84f0390450b0 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Wed, 8 Jun 2016 09:50:36 +0200 Subject: [PATCH 03/16] Disable ASKUSER policy by default This is needed for UI-less Tizen (potential) profiles. Change-Id: Icb4a801b598c074412c770047cbc7686780ed704 --- CMakeLists.txt | 1 + src/common/config.cpp | 5 ++++ src/common/cynara.cpp | 63 ++++++++++++++++++++++++--------------------- src/common/include/config.h | 3 +++ src/common/service_impl.cpp | 18 +++++++------ 5 files changed, 52 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 040dc3c..ec5954f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}") ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"") ADD_DEFINITIONS("-DSMACK_ENABLED") +#ADD_DEFINITIONS("-DASKUSER_ENABLED") OPTION(DPL_WITH_DLOG "DPL DLOG backend" ON) OPTION(DPL_WITH_SYSTEMD_JOURNAL "DPL systemd-journal backend" OFF) diff --git a/src/common/config.cpp b/src/common/config.cpp index 8c8dd9e..49f87a5 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -47,6 +47,11 @@ const std::string APPS_NAME_FILE = "apps-names"; const std::string SKEL_DIR = "/etc/skel"; const std::string PRIVACY_POLICY_DESC = "Ask user"; +#ifdef ASKUSER_ENABLED +const bool IS_ASKUSER_ENABLED = true; +#else +const bool IS_ASKUSER_ENABLED = false; +#endif }; } /* namespace SecurityManager */ diff --git a/src/common/cynara.cpp b/src/common/cynara.cpp index d2c26d2..f9d1d5f 100644 --- a/src/common/cynara.cpp +++ b/src/common/cynara.cpp @@ -335,29 +335,30 @@ void CynaraAdmin::UpdateAppPolicy( static_cast(CynaraAdminPolicy::Operation::Allow), policies); - int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); - - std::vector privacyPrivileges; - for (auto &p : privileges) - if (isPrivacy(p)) - privacyPrivileges.push_back(p); - - // 2nd, performing operation on PRIVACY_MANAGER bucket for all affected users - if (user == CYNARA_ADMIN_WILDCARD) { - // perform bucket setting for all users in the system, app is installed for everyone - std::vector users; - ListUsers(users); - for (uid_t id : users) { - calcPolicies(std::to_string(id), privacyPrivileges, - Buckets.at(Bucket::PRIVACY_MANAGER), + if (Config::IS_ASKUSER_ENABLED) { + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + + std::vector privacyPrivileges; + for (auto &p : privileges) + if (isPrivacy(p)) + privacyPrivileges.push_back(p); + + // 2nd, performing operation on PRIVACY_MANAGER bucket for all affected users + if (user == CYNARA_ADMIN_WILDCARD) { + // perform bucket setting for all users in the system, app is installed for everyone + std::vector users; + ListUsers(users); + for (uid_t id : users) { + calcPolicies(std::to_string(id), privacyPrivileges, + Buckets.at(Bucket::PRIVACY_MANAGER), + askUserPolicy, policies); + } + } else { + // local single user installation, do it only for that particular user + calcPolicies(user, privacyPrivileges, Buckets.at(Bucket::PRIVACY_MANAGER), askUserPolicy, policies); } - } else { - // local single user installation, do it only for that particular user - calcPolicies(user, privacyPrivileges, Buckets.at(Bucket::PRIVACY_MANAGER), - askUserPolicy, policies); } - SetPolicies(policies); } @@ -409,22 +410,24 @@ void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType, Buckets.at(bucket), Buckets.at(Bucket::MAIN))); - // for each global app: retrieve its privacy-related privileges and set - // their policy in PRIVACY_MANAGER bucket to "Ask user" - int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + if (Config::IS_ASKUSER_ENABLED) { + // for each global app: retrieve its privacy-related privileges and set + // their policy in PRIVACY_MANAGER bucket to "Ask user" + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); - std::vector appPolicies; - CynaraAdmin::getInstance().ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS), - CYNARA_ADMIN_ANY, CYNARA_ADMIN_WILDCARD, - CYNARA_ADMIN_ANY, appPolicies); + std::vector appPolicies; + CynaraAdmin::getInstance().ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS), + CYNARA_ADMIN_ANY, CYNARA_ADMIN_WILDCARD, + CYNARA_ADMIN_ANY, appPolicies); - for (CynaraAdminPolicy &policy : appPolicies) - if (isPrivacy(policy.privilege)) - policies.push_back(CynaraAdminPolicy(policy.client, + for (CynaraAdminPolicy &policy : appPolicies) + if (isPrivacy(policy.privilege)) + policies.push_back(CynaraAdminPolicy(policy.client, userStr, policy.privilege, askUserPolicy, Buckets.at(Bucket::PRIVACY_MANAGER))); + } CynaraAdmin::getInstance().SetPolicies(policies); } diff --git a/src/common/include/config.h b/src/common/include/config.h index 01d0f79..b874e01 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -48,6 +48,9 @@ extern const std::string SKEL_DIR; /* Ask-user policy description */ extern const std::string PRIVACY_POLICY_DESC; + +/* true if privacy-related privileges should result in UI-popup question*/ +extern const bool IS_ASKUSER_ENABLED; }; } /* namespace SecurityManager */ diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 40bf386..e42a728 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -402,14 +402,16 @@ void ServiceImpl::getTizen2XApps(SmackRules::PkgsApps &pkgsApps) bool ServiceImpl::isPrivilegePrivacy(const std::string &privilege) { - int ret = privilege_info_is_privacy(privilege.c_str()); - if (ret == 1) - return true; - if (ret != 0) - LogError("privilege_info_is_privacy called with " << privilege << " returned error: " << ret); - // FIXME: we should probably disallow such installation where privilege is not known - // However, currently privielge-checker seems to return -1 with so many real privileges - // that it would make ask-user testing impossible. + if (Config::IS_ASKUSER_ENABLED) { + int ret = privilege_info_is_privacy(privilege.c_str()); + if (ret == 1) + return true; + if (ret != 0) + LogError("privilege_info_is_privacy called with " << privilege << " returned error: " << ret); + // FIXME: we should probably disallow such installation where privilege is not known + // However, currently privielge-checker seems to return -1 with so many real privileges + // that it would make ask-user testing impossible. + } return false; } -- 2.7.4 From 460417c9c636b9dc1409b888593e0a2a86b81b33 Mon Sep 17 00:00:00 2001 From: Radoslaw Bartosiak Date: Fri, 10 Jun 2016 17:14:09 +0200 Subject: [PATCH 04/16] Fix installation user mangling Set global user as the owner of preloaded applications and applications installed globally. Change-Id: Idb3f194aacefa7afaa047de6bfdfdb1bee6b8736 Signed-off-by: Radoslaw Bartosiak --- src/common/service_impl.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index e42a728..a14491f 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -262,12 +262,11 @@ void ServiceImpl::setRequestDefaultValues(uid_t& uid, int& installationType) { uid_t globalUid = getGlobalUserId(); - if (uid == 0) - uid = globalUid; - if (installationType == SM_APP_INSTALL_NONE) - installationType = (uid == globalUid) ? SM_APP_INSTALL_GLOBAL : - SM_APP_INSTALL_LOCAL; + installationType = (uid == 0) ? SM_APP_INSTALL_GLOBAL : SM_APP_INSTALL_LOCAL; + if ((installationType == SM_APP_INSTALL_GLOBAL) + || (installationType == SM_APP_INSTALL_PRELOADED)) + uid = globalUid; } void ServiceImpl::installRequestMangle(app_inst_req &req, std::string &cynaraUserStr) -- 2.7.4 From 81c23c4d28a67b39c78b79418fb657206bd31974 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Fri, 10 Jun 2016 13:59:00 +0200 Subject: [PATCH 05/16] Prepare setup_smack client function for running without CAP_MAC_ADMIN Without CAP_MAC_ADMIN we'll not be able to relabel opened sockets, which, after analysis, seems unnecessary. Change-Id: I2c2d7af60cbfe79e9a5edc9ee56ef5e1ed9edbf7 --- src/client/client-security-manager.cpp | 64 ++++++---------------------------- 1 file changed, 11 insertions(+), 53 deletions(-) diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index f88254e..e44b909 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -321,62 +321,20 @@ int security_manager_get_app_pkgid(char **pkg_name, const char *app_name) static bool setup_smack(const char *label) { - int labelSize = strlen(label); - - // Set Smack label for open socket file descriptors - - std::unique_ptr> dir( - opendir("/proc/self/fd"), closedir); - if (!dir.get()) { - LogError("Unable to read list of open file descriptors: " << - GetErrnoString(errno)); + /* Here we also should change open socket labels for future process identification. + However, since Smack support for "dyntransition"-like feature will be enabled soon, + relabeling the sockets will no longer be possible. + + After careful review it was found that only opened sockets are ones to systemd + (user and system session) and enlightment. Both services are not integrated with Cynara + and seem to be fine with these sockets retaining IPIN/IPOUT "User" label. + */ + // Set Smack label of current process + if (smack_set_label_for_self(label) != 0) { + LogError("Failed to set Smack label for application: " << label); return SECURITY_MANAGER_ERROR_UNKNOWN; } - do { - errno = 0; - struct dirent *dirEntry = readdir(dir.get()); - if (dirEntry == nullptr) { - if (errno == 0) // NULL return value also signals end of directory - break; - - LogError("Unable to read list of open file descriptors: " << - GetErrnoString(errno)); - return SECURITY_MANAGER_ERROR_UNKNOWN; - } - - // Entries with numerical names specify file descriptors, ignore the rest - if (!isdigit(dirEntry->d_name[0])) - continue; - - struct stat statBuf; - int fd = atoi(dirEntry->d_name); - int ret = fstat(fd, &statBuf); - if (ret != 0) { - LogWarning("fstat failed on file descriptor " << fd << ": " << - GetErrnoString(errno)); - continue; - } - if (S_ISSOCK(statBuf.st_mode)) { - ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, label, labelSize, 0); - if (ret != 0) { - LogError("Setting Smack label failed on file descriptor " << - fd << ": " << GetErrnoString(errno)); - return SECURITY_MANAGER_ERROR_UNKNOWN; - } - - ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, label, labelSize, 0); - if (ret != 0) { - LogError("Setting Smack label failed on file descriptor " << - fd << ": " << GetErrnoString(errno)); - return SECURITY_MANAGER_ERROR_UNKNOWN; - } - } - } while (true); - - // Set Smack label of current process - smack_set_label_for_self(label); - return SECURITY_MANAGER_SUCCESS; } -- 2.7.4 From fea6a61d41bdbca8982a2d4c9cadc336f36495de Mon Sep 17 00:00:00 2001 From: Zbigniew Jasinski Date: Wed, 8 Jun 2016 12:03:26 +0200 Subject: [PATCH 06/16] Added parameter mode and made more generic getDirContents function Like previously, for files in dir use getFilesFromDirectory. For listing directories only - getDirsFromDirectory. Change-Id: Ic7ed060fcbaef90e3a6f15d8815a3f1ec522d062 Signed-off-by: Zbigniew Jasinski --- src/common/filesystem.cpp | 13 +++++++++++-- src/common/include/filesystem.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/common/filesystem.cpp b/src/common/filesystem.cpp index 5ad5232..6582104 100644 --- a/src/common/filesystem.cpp +++ b/src/common/filesystem.cpp @@ -42,8 +42,18 @@ namespace SecurityManager { namespace FS { +FileNameVector getDirsFromDirectory(const std::string &path) +{ + return getDirContents(path, S_IFDIR); +} + FileNameVector getFilesFromDirectory(const std::string &path) { + return getDirContents(path, S_IFREG); +} + +FileNameVector getDirContents(const std::string &path, const mode_t &mode) +{ FileNameVector result; dirent tmp, *ptr; int err; @@ -68,9 +78,8 @@ FileNameVector getFilesFromDirectory(const std::string &path) ThrowMsg(FS::Exception::FileError, "Error reading: " << ptr->d_name); } - if (S_ISREG(finfo.st_mode)) { + if ((finfo.st_mode & S_IFMT) == mode) result.push_back(ptr->d_name); - } } return result; diff --git a/src/common/include/filesystem.h b/src/common/include/filesystem.h index e2f15f8..9806edb 100644 --- a/src/common/include/filesystem.h +++ b/src/common/include/filesystem.h @@ -34,7 +34,9 @@ namespace FS { typedef std::vector FileNameVector; +FileNameVector getDirContents(const std::string &path, const mode_t &mode); FileNameVector getFilesFromDirectory(const std::string &path); +FileNameVector getDirsFromDirectory(const std::string &path); } // namespace FS } // nanespace SecurityManager -- 2.7.4 From 6eef187ab9b81e83744e96bedc9c667598e588f6 Mon Sep 17 00:00:00 2001 From: Zbigniew Jasinski Date: Wed, 1 Jun 2016 17:43:29 +0200 Subject: [PATCH 07/16] Threads security context synchronization - use lambda as signal handler - return error if not all threads synced - change NULL to nullptr - added std::atomic_thread_fence for memory synchronization - block SIGUSR1 signal during threads counting - set signal set to empty - added waiting loop for signal propagation - reset signal handler after threads synced, not before - synchronization of both: Smack labels and Linux capabilities Change-Id: Ia9d6a503e88523c387ab1ba30e0e9a5a94f05a5c Signed-off-by: Zbigniew Jasinski --- src/client/client-security-manager.cpp | 157 +++++++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 5 deletions(-) diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index e44b909..40b037f 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -39,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -53,6 +57,8 @@ #include #include +#include "filesystem.h" + static const char *EMPTY = ""; /** @@ -69,6 +75,14 @@ static std::map lib_retcode_string_map = { {SECURITY_MANAGER_ERROR_ACCESS_DENIED, "Insufficient privileges"}, }; +// variables & definitions for thread security attributes +static std::string g_app_label; +static std::atomic g_threads_count; +static std::map g_tid_attr_current_map; +static bool g_smack_fs_path; +static cap_t g_cap; +#define MAX_SIG_WAIT_TIME 1000 + SECURITY_MANAGER_API const char *security_manager_strerror(enum lib_retcode rc) { @@ -467,6 +481,138 @@ static int getAppGroups(const std::string appName, std::vector &groups) return groupNamesToGids(groupNames, groups); } +inline static uid_t gettid() +{ + return syscall(SYS_gettid); +} + +inline static void tkill(uid_t tid) +{ + syscall(SYS_tkill, tid, SIGUSR1); +} + +inline static int label_for_self_internal() +{ + int fd; + int ret; + fd = open(g_tid_attr_current_map[gettid()].c_str(), O_WRONLY); + if (fd < 0) { + return -1; + } + ret = write(fd, g_app_label.c_str(), g_app_label.length()); + close(fd); + + if (ret < 0) { + return -1; + } + return 0; +} + +static inline int security_manager_sync_threads_internal(const char *app_name) +{ + LogDebug("security_manager_sync_threads_internal called for app_name: " << app_name); + + if (ATOMIC_INT_LOCK_FREE != 2) { + LogError("std::atomic is not always lock free"); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + FS::FileNameVector files = FS::getDirsFromDirectory("/proc/self/task"); + uid_t cur_tid = gettid(); + + g_app_label = SecurityManager::SmackLabels::generateAppLabel(app_name); + g_threads_count = 0; + g_tid_attr_current_map.clear(); + g_smack_fs_path = smack_smackfs_path() != NULL; + g_cap = cap_init(); + + if (!g_cap) { + LogError("Unable to allocate capability object"); + return SECURITY_MANAGER_ERROR_MEMORY; + } + + if (cap_clear(g_cap)) { + LogError("Unable to initialize capability object"); + cap_free(g_cap); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + std::atomic_thread_fence(std::memory_order_release); + + struct sigaction act; + struct sigaction old; + memset(&act, '\0', sizeof(act)); + memset(&old, '\0', sizeof(old)); + + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = [](int signo) { + (void)signo; + + std::atomic_thread_fence(std::memory_order_acquire); + + if (g_smack_fs_path) + if(label_for_self_internal() != 0) + return; + + if (cap_set_proc(g_cap)) + return; + + g_threads_count++; + }; + + if (sigaction(SIGUSR1, &act, &old) < 0) { + LogError("Error in sigaction()"); + cap_free(g_cap); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + int sent_signals_count = 0; + + for (auto const &e : files) { + if (e.compare(".") == 0 || e.compare("..") == 0) + continue; + + int tid = atoi(e.c_str()); + if (tid == static_cast(cur_tid)) + continue; + + g_tid_attr_current_map[tid] = "/proc/self/task/" + std::to_string(tid) + "/attr/current"; + sent_signals_count++; + tkill(tid); + } + + LogDebug("sent_signals_count: " << sent_signals_count); + + for (int i = 0; g_threads_count != sent_signals_count && i < MAX_SIG_WAIT_TIME; ++i) + usleep(1000); // 1 ms + + sigaction(SIGUSR1, &old, nullptr); + + if (g_threads_count != sent_signals_count) { + LogError("Not all threads synchronized: threads done: " << g_threads_count); + cap_free(g_cap); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + if (g_smack_fs_path) + if (smack_set_label_for_self(g_app_label.c_str()) != 0) { + LogError("smack_set_label_for_self failed"); + cap_free(g_cap); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + if (cap_set_proc(g_cap)) { + LogError("Can't drop main thread capabilities"); + cap_free(g_cap); + return SECURITY_MANAGER_ERROR_UNKNOWN; + } + + cap_free(g_cap); + + return SECURITY_MANAGER_SUCCESS; +} + SECURITY_MANAGER_API int security_manager_set_process_groups_from_appid(const char *app_name) { @@ -551,17 +697,18 @@ int security_manager_prepare_app(const char *app_name) LogDebug("security_manager_prepare_app() called"); int ret; - ret = security_manager_set_process_label_from_appid(app_name); - if (ret != SECURITY_MANAGER_SUCCESS) - return ret; - ret = security_manager_set_process_groups_from_appid(app_name); if (ret != SECURITY_MANAGER_SUCCESS) { LogWarning("Unable to setup process groups for application. Privileges with direct access to resources will not work."); ret = SECURITY_MANAGER_SUCCESS; } - ret = security_manager_drop_process_privileges(); + ret = security_manager_sync_threads_internal(app_name); + if (ret != SECURITY_MANAGER_SUCCESS) { + LogError("Can't properly setup application threads (Smack label & capabilities)"); + return ret; + } + return ret; } -- 2.7.4 From b1e0fb389d0a8c2230985b3ea7aab7d363a7e403 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Thu, 14 Jan 2016 16:48:19 +0100 Subject: [PATCH 08/16] Add check if privileges were properly dropped Check if every thread in process has same stats as thread calling security_manager_prepare_app() and exit from process if they do not. Change-Id: I008c2b8e442edb6a5f9f1d74bf13f95465b6bdca Signed-off-by: Rafal Krypa --- packaging/security-manager.spec | 1 + src/client/CMakeLists.txt | 2 + src/client/check-proper-drop.cpp | 129 +++++++++++++++++++++++++++++++++ src/client/client-security-manager.cpp | 41 +++++++---- src/client/include/check-proper-drop.h | 76 +++++++++++++++++++ 5 files changed, 236 insertions(+), 13 deletions(-) create mode 100644 src/client/check-proper-drop.cpp create mode 100644 src/client/include/check-proper-drop.h diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec index 20a84bd..82c27f2 100644 --- a/packaging/security-manager.spec +++ b/packaging/security-manager.spec @@ -15,6 +15,7 @@ BuildRequires: cmake BuildRequires: zip # BuildRequires: pkgconfig(dlog) BuildRequires: libattr-devel +BuildRequires: pkgconfig(libprocps) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(libcap) BuildRequires: pkgconfig(libsystemd-daemon) diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index f934617..44d898f 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -2,6 +2,7 @@ PKG_CHECK_MODULES(CLIENT_DEP REQUIRED libsmack libcap + libprocps ) SET(CLIENT_VERSION_MAJOR 1) @@ -24,6 +25,7 @@ SET(CLIENT_SOURCES ${CLIENT_PATH}/client-common.cpp ${CLIENT_PATH}/client-offline.cpp ${CLIENT_PATH}/client-label-monitor.cpp + ${CLIENT_PATH}/check-proper-drop.cpp ) ADD_LIBRARY(${TARGET_CLIENT} SHARED ${CLIENT_SOURCES}) diff --git a/src/client/check-proper-drop.cpp b/src/client/check-proper-drop.cpp new file mode 100644 index 0000000..4d136c5 --- /dev/null +++ b/src/client/check-proper-drop.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 + */ +/* + * @file check-proper-drop.cpp + * @author Rafal Krypa + * @version 1.0 + * @brief Implementation of proper privilege dropping check utilities + */ + +#include "check-proper-drop.h" +#include "smack-labels.h" +#include + +#include + +#include +#include + +namespace SecurityManager { + +using proctabPtr = std::unique_ptr; +using capPtr = std::unique_ptr<_cap_struct, int (*)(void*)>; +using capStrPtr = std::unique_ptr; + +CheckProperDrop::~CheckProperDrop() +{ + for (const auto &thread : m_threads) + freeproc(thread); + freeproc(m_proc); +} + +void CheckProperDrop::getThreads() +{ + pid_t pid[2] = {m_pid, 0}; + proctabPtr PT(openproc(PROC_FILLSTATUS | PROC_PID, pid), closeproc); + if (!PT) + ThrowMsg(Exception::ProcError, + "Unable to open proc interface"); + + m_proc = readproc(PT.get(), nullptr); + if (!m_proc) + ThrowMsg(Exception::ProcError, + "Unable read process information for " << pid); + + proc_t *thread; + while ((thread = readtask(PT.get(), m_proc, nullptr))) + if (thread->tid != m_pid) + m_threads.push_back(thread); +} + +bool CheckProperDrop::checkThreads() +{ +#define REPORT_THREAD_ERROR(TID, NAME, VAL1, VAL2) { \ + LogError("Invalid value of " << (NAME) << " for thread " << (TID) << "." \ + << ". Process has " << (VAL1) << ", thread has " << (VAL2) << "."); \ + return false; \ +} + +#define CHECK_THREAD_CRED_FIELD(P, T, FIELD) { \ + int pval = (P)->FIELD, tval = (T)->FIELD; \ + if (pval != tval) \ + REPORT_THREAD_ERROR((T)->tid, #FIELD, pval, tval); \ +} + + std::string smackProc = SmackLabels::getSmackLabelFromPid(m_pid); + + capPtr capProc(cap_get_pid(m_pid), cap_free); + if (!capProc) + ThrowMsg(Exception::CapError, + "Unable to get capabilities for " << m_pid); + + capStrPtr capStrProc(cap_to_text(capProc.get(), nullptr), cap_free); + if (!capStrProc) + ThrowMsg(Exception::CapError, + "Unable to get capabilities for " << m_pid); + + for (const auto &thread : m_threads) { + capPtr capThread(cap_get_pid(thread->tid), cap_free); + if (!capThread) + ThrowMsg(Exception::CapError, + "Unable to get capabilities for " << thread->tid); + + if (cap_compare(capProc.get(), capThread.get())) { + capStrPtr capStrThread(cap_to_text(capThread.get(), nullptr), cap_free); + if (!capStrThread) + ThrowMsg(Exception::CapError, "Unable to get capabilities for " << thread->tid); + + REPORT_THREAD_ERROR(thread->tid, "capabilities", + capStrProc.get(), capStrThread.get()); + } + + std::string smackThread = SmackLabels::getSmackLabelFromPid(thread->tid); + if (smackProc != smackThread) + REPORT_THREAD_ERROR(thread->tid, "Smack label", + smackProc, smackThread); + + if (strcmp(m_proc->supgid, thread->supgid)) + REPORT_THREAD_ERROR(thread->tid, "Supplementary groups", + m_proc->supgid, thread->supgid); + + CHECK_THREAD_CRED_FIELD(m_proc, thread, euid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, egid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, ruid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, rgid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, suid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, sgid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, fuid); + CHECK_THREAD_CRED_FIELD(m_proc, thread, fgid); + } + + return true; +} + +} // namespace SecurityManager diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 40b037f..55109fc 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -26,6 +26,7 @@ */ #include +#include #include #include #include @@ -52,6 +53,7 @@ #include #include #include +#include #include #include @@ -694,22 +696,35 @@ int security_manager_drop_process_privileges(void) SECURITY_MANAGER_API int security_manager_prepare_app(const char *app_name) { - LogDebug("security_manager_prepare_app() called"); - int ret; + return try_catch([&] { + LogDebug("security_manager_prepare_app() called"); + int ret; - ret = security_manager_set_process_groups_from_appid(app_name); - if (ret != SECURITY_MANAGER_SUCCESS) { - LogWarning("Unable to setup process groups for application. Privileges with direct access to resources will not work."); - ret = SECURITY_MANAGER_SUCCESS; - } + ret = security_manager_set_process_groups_from_appid(app_name); + if (ret != SECURITY_MANAGER_SUCCESS) { + LogWarning("Unable to setup process groups for application. Privileges with direct access to resources will not work."); + } - ret = security_manager_sync_threads_internal(app_name); - if (ret != SECURITY_MANAGER_SUCCESS) { - LogError("Can't properly setup application threads (Smack label & capabilities)"); - return ret; - } + ret = security_manager_sync_threads_internal(app_name); + if (ret != SECURITY_MANAGER_SUCCESS) { + LogError("Can't properly setup application threads (Smack label & capabilities)"); + exit(EXIT_FAILURE); + } - return ret; + try { + CheckProperDrop cpd; + cpd.getThreads(); + if (!cpd.checkThreads()) { + LogError("Privileges haven't been properly dropped for the whole process"); + exit(EXIT_FAILURE); + } + } catch (const SecurityManager::Exception &e) { + LogError("Error while checking privileges of the process: " << e.DumpToString()); + exit(EXIT_FAILURE); + } + + return ret; + }); } SECURITY_MANAGER_API diff --git a/src/client/include/check-proper-drop.h b/src/client/include/check-proper-drop.h new file mode 100644 index 0000000..ad1df5b --- /dev/null +++ b/src/client/include/check-proper-drop.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 + */ +/* + * @file check-proper-drop.h + * @author Rafal Krypa + * @version 1.0 + * @brief Definition of proper privilege dropping check utilities + */ + +#ifndef SECURITY_MANAGER_CHECK_PROPER_DROP_ +#define SECURITY_MANAGER_CHECK_PROPER_DROP_ + +#include + +#include +#include + +#include + +namespace SecurityManager { + +class CheckProperDrop { +public: + class Exception { + public: + DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, ProcError) + DECLARE_EXCEPTION_TYPE(Base, CapError) + }; + + ~CheckProperDrop(); + CheckProperDrop(pid_t pid = getpid()) : m_pid(pid) {}; + + /** + * Fetch credentials of the process and all its threads. + * Must be called before checkThreads(). + */ + void getThreads(); + + /** + * Check whether all threads of the process has properly aligned + * credentials: + * - uids + * - gids + * - capabilities + * - Smack labels + * + * It will terminate the calling process if any thread has different + * value than the other threads. This prevents security risks associated + * with improperly dropped privileges during application launch. + */ + bool checkThreads(); + +private: + pid_t m_pid; + proc_t *m_proc = nullptr; + std::vector m_threads; +}; + +} // namespace SecurityManager +#endif /* SECURITY_MANAGER_CHECK_PROPER_DROP_H_ */ -- 2.7.4 From c8d13905b49e825b71994fcb68bc075a70e20294 Mon Sep 17 00:00:00 2001 From: Yunjin Lee Date: Fri, 17 Jun 2016 13:20:31 +0900 Subject: [PATCH 09/16] Add core privileges - antivirus.* privileges: antivirus.admin, antivirus.scan, antivirus.webprotect - dpm.* privileges: dpm.bluetooth, dpm.browser, dpm.camera, dpm.clipboard, dpm.debugging, dpm.email, dpm.location, dpm.lock, dpm.message, dpm.microphone, dpm.password, dpm.security, dpm.settings, dpm.storage, dpm.usb, dpm.wifi, dpm.wipe, dpm.zone It refers to https://review.tizen.org/gerrit/#/c/75182/ Change-Id: I8740097ba9ef12100426e56e9f69ca6799c449b4 Signed-off-by: Yunjin Lee --- policy/usertype-admin.profile | 21 +++++++++++++++++++++ policy/usertype-guest.profile | 21 +++++++++++++++++++++ policy/usertype-normal.profile | 21 +++++++++++++++++++++ policy/usertype-system.profile | 21 +++++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/policy/usertype-admin.profile b/policy/usertype-admin.profile index a20b34c..b010961 100644 --- a/policy/usertype-admin.profile +++ b/policy/usertype-admin.profile @@ -5,6 +5,9 @@ * http://tizen.org/privilege/alarm.get * http://tizen.org/privilege/alarm.set * http://tizen.org/privilege/antivirus +* http://tizen.org/privilege/antivirus.admin +* http://tizen.org/privilege/antivirus.scan +* http://tizen.org/privilege/antivirus.webprotect * http://tizen.org/privilege/apphistory.read * http://tizen.org/privilege/appmanager.kill * http://tizen.org/privilege/appmanager.kill.bgapp @@ -25,6 +28,24 @@ * http://tizen.org/privilege/datasharing * http://tizen.org/privilege/display * http://tizen.org/privilege/download +* http://tizen.org/privilege/dpm.bluetooth +* http://tizen.org/privilege/dpm.browser +* http://tizen.org/privilege/dpm.camera +* http://tizen.org/privilege/dpm.clipboard +* http://tizen.org/privilege/dpm.debugging +* http://tizen.org/privilege/dpm.email +* http://tizen.org/privilege/dpm.location +* http://tizen.org/privilege/dpm.lock +* http://tizen.org/privilege/dpm.message +* http://tizen.org/privilege/dpm.microphone +* http://tizen.org/privilege/dpm.password +* http://tizen.org/privilege/dpm.security +* http://tizen.org/privilege/dpm.settings +* http://tizen.org/privilege/dpm.storage +* http://tizen.org/privilege/dpm.usb +* http://tizen.org/privilege/dpm.wifi +* http://tizen.org/privilege/dpm.wipe +* http://tizen.org/privilege/dpm.zone * http://tizen.org/privilege/email * http://tizen.org/privilege/email.admin * http://tizen.org/privilege/externalstorage diff --git a/policy/usertype-guest.profile b/policy/usertype-guest.profile index 702ea44..b27a091 100644 --- a/policy/usertype-guest.profile +++ b/policy/usertype-guest.profile @@ -5,6 +5,9 @@ * http://tizen.org/privilege/alarm.get * http://tizen.org/privilege/alarm.set * http://tizen.org/privilege/antivirus +* http://tizen.org/privilege/antivirus.admin +* http://tizen.org/privilege/antivirus.scan +* http://tizen.org/privilege/antivirus.webprotect * http://tizen.org/privilege/apphistory.read * http://tizen.org/privilege/appmanager.kill * http://tizen.org/privilege/appmanager.kill.bgapp @@ -25,6 +28,24 @@ * http://tizen.org/privilege/datasharing * http://tizen.org/privilege/display * http://tizen.org/privilege/download +* http://tizen.org/privilege/dpm.bluetooth +* http://tizen.org/privilege/dpm.browser +* http://tizen.org/privilege/dpm.camera +* http://tizen.org/privilege/dpm.clipboard +* http://tizen.org/privilege/dpm.debugging +* http://tizen.org/privilege/dpm.email +* http://tizen.org/privilege/dpm.location +* http://tizen.org/privilege/dpm.lock +* http://tizen.org/privilege/dpm.message +* http://tizen.org/privilege/dpm.microphone +* http://tizen.org/privilege/dpm.password +* http://tizen.org/privilege/dpm.security +* http://tizen.org/privilege/dpm.settings +* http://tizen.org/privilege/dpm.storage +* http://tizen.org/privilege/dpm.usb +* http://tizen.org/privilege/dpm.wifi +* http://tizen.org/privilege/dpm.wipe +* http://tizen.org/privilege/dpm.zone * http://tizen.org/privilege/email * http://tizen.org/privilege/email.admin * http://tizen.org/privilege/externalstorage diff --git a/policy/usertype-normal.profile b/policy/usertype-normal.profile index 8a062f5..50fead9 100644 --- a/policy/usertype-normal.profile +++ b/policy/usertype-normal.profile @@ -5,6 +5,9 @@ * http://tizen.org/privilege/alarm.get * http://tizen.org/privilege/alarm.set * http://tizen.org/privilege/antivirus +* http://tizen.org/privilege/antivirus.admin +* http://tizen.org/privilege/antivirus.scan +* http://tizen.org/privilege/antivirus.webprotect * http://tizen.org/privilege/apphistory.read * http://tizen.org/privilege/appmanager.kill * http://tizen.org/privilege/appmanager.kill.bgapp @@ -25,6 +28,24 @@ * http://tizen.org/privilege/datasharing * http://tizen.org/privilege/display * http://tizen.org/privilege/download +* http://tizen.org/privilege/dpm.bluetooth +* http://tizen.org/privilege/dpm.browser +* http://tizen.org/privilege/dpm.camera +* http://tizen.org/privilege/dpm.clipboard +* http://tizen.org/privilege/dpm.debugging +* http://tizen.org/privilege/dpm.email +* http://tizen.org/privilege/dpm.location +* http://tizen.org/privilege/dpm.lock +* http://tizen.org/privilege/dpm.message +* http://tizen.org/privilege/dpm.microphone +* http://tizen.org/privilege/dpm.password +* http://tizen.org/privilege/dpm.security +* http://tizen.org/privilege/dpm.settings +* http://tizen.org/privilege/dpm.storage +* http://tizen.org/privilege/dpm.usb +* http://tizen.org/privilege/dpm.wifi +* http://tizen.org/privilege/dpm.wipe +* http://tizen.org/privilege/dpm.zone * http://tizen.org/privilege/email * http://tizen.org/privilege/email.admin * http://tizen.org/privilege/externalstorage diff --git a/policy/usertype-system.profile b/policy/usertype-system.profile index aa9893e..7b2fd7b 100644 --- a/policy/usertype-system.profile +++ b/policy/usertype-system.profile @@ -5,6 +5,9 @@ * http://tizen.org/privilege/alarm.get * http://tizen.org/privilege/alarm.set * http://tizen.org/privilege/antivirus +* http://tizen.org/privilege/antivirus.admin +* http://tizen.org/privilege/antivirus.scan +* http://tizen.org/privilege/antivirus.webprotect * http://tizen.org/privilege/apphistory.read * http://tizen.org/privilege/appmanager.kill * http://tizen.org/privilege/appmanager.kill.bgapp @@ -25,6 +28,24 @@ * http://tizen.org/privilege/datasharing * http://tizen.org/privilege/display * http://tizen.org/privilege/download +* http://tizen.org/privilege/dpm.bluetooth +* http://tizen.org/privilege/dpm.browser +* http://tizen.org/privilege/dpm.camera +* http://tizen.org/privilege/dpm.clipboard +* http://tizen.org/privilege/dpm.debugging +* http://tizen.org/privilege/dpm.email +* http://tizen.org/privilege/dpm.location +* http://tizen.org/privilege/dpm.lock +* http://tizen.org/privilege/dpm.message +* http://tizen.org/privilege/dpm.microphone +* http://tizen.org/privilege/dpm.password +* http://tizen.org/privilege/dpm.security +* http://tizen.org/privilege/dpm.settings +* http://tizen.org/privilege/dpm.storage +* http://tizen.org/privilege/dpm.usb +* http://tizen.org/privilege/dpm.wifi +* http://tizen.org/privilege/dpm.wipe +* http://tizen.org/privilege/dpm.zone * http://tizen.org/privilege/email * http://tizen.org/privilege/email.admin * http://tizen.org/privilege/externalstorage -- 2.7.4 From 14738008938625cf9394855a70b5e0f2f1079cdb Mon Sep 17 00:00:00 2001 From: Yunjin Lee Date: Tue, 10 May 2016 15:58:21 +0900 Subject: [PATCH 10/16] Add internal privilege for app debugging : when specific option is set, app-installers will add this privilege to app privilege list Change-Id: I75cd6c567d67c3963e0629c2dd2f2e5e7c7bebdf Signed-off-by: Yunjin Lee --- policy/usertype-admin.profile | 1 + policy/usertype-guest.profile | 1 + policy/usertype-normal.profile | 1 + policy/usertype-system.profile | 1 + 4 files changed, 4 insertions(+) diff --git a/policy/usertype-admin.profile b/policy/usertype-admin.profile index b010961..0f4972e 100644 --- a/policy/usertype-admin.profile +++ b/policy/usertype-admin.profile @@ -118,3 +118,4 @@ * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block * http://tizen.org/privilege/internal/usermanagement +* http://tizen.org/privilege/internal/appdebugging diff --git a/policy/usertype-guest.profile b/policy/usertype-guest.profile index b27a091..fdfd620 100644 --- a/policy/usertype-guest.profile +++ b/policy/usertype-guest.profile @@ -117,3 +117,4 @@ * http://tizen.org/privilege/internal/buxton/telephony * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block +* http://tizen.org/privilege/internal/appdebugging diff --git a/policy/usertype-normal.profile b/policy/usertype-normal.profile index 50fead9..e144020 100644 --- a/policy/usertype-normal.profile +++ b/policy/usertype-normal.profile @@ -117,3 +117,4 @@ * http://tizen.org/privilege/internal/buxton/telephony * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block +* http://tizen.org/privilege/internal/appdebugging diff --git a/policy/usertype-system.profile b/policy/usertype-system.profile index 7b2fd7b..0af9203 100644 --- a/policy/usertype-system.profile +++ b/policy/usertype-system.profile @@ -117,3 +117,4 @@ * http://tizen.org/privilege/internal/buxton/telephony * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block +* http://tizen.org/privilege/internal/appdebugging -- 2.7.4 From e7577894248f744606310452be0a78255e20aed2 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Thu, 16 Jun 2016 14:22:12 +0200 Subject: [PATCH 11/16] Release version 1.1.7 Add internal privilege for app debugging Add core privileges Add check if privileges were properly dropped Threads security context synchronization Added parameter mode and made more generic getDirContents function Prepare setup_smack client function for running without CAP_MAC_ADMIN Fix installation user mangling Disable ASKUSER policy by default Fix policy access control for accessing another user's policy Add proper policy setup for privacy-related privileges Fix doxygen comments Change-Id: I72faf5a7c10fe28cde0e6ed22bb8fe7c82189109 --- packaging/security-manager.changes | 14 ++++++++++++++ packaging/security-manager.spec | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packaging/security-manager.changes b/packaging/security-manager.changes index a8012b4..45b29d6 100644 --- a/packaging/security-manager.changes +++ b/packaging/security-manager.changes @@ -1,3 +1,17 @@ +* Thu June 16 2016 Tomasz Swierczek +- Version 1.1.7 +- Add internal privilege for app debugging +- Add core privileges +- Add check if privileges were properly dropped +- Threads security context synchronization +- Added parameter mode and made more generic getDirContents function +- Prepare setup_smack client function for running without CAP_MAC_ADMIN +- Fix installation user mangling +- Disable ASKUSER policy by default +- Fix policy access control for accessing another user's policy +- Add proper policy setup for privacy-related privileges +- Fix doxygen comments + * Wed May 25 2016 Tomasz Swierczek - Version 1.1.6 - Fix issues with local user app instalaltion and inotify file watches. diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec index 82c27f2..4b45632 100644 --- a/packaging/security-manager.spec +++ b/packaging/security-manager.spec @@ -1,6 +1,6 @@ Name: security-manager Summary: Security manager and utilities -Version: 1.1.6 +Version: 1.1.7 Release: 0 Group: Security/Service License: Apache-2.0 -- 2.7.4 From e4535a7e6b52d38b6b218ac473a0c07ec84f41c2 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Thu, 7 Apr 2016 12:57:01 +0200 Subject: [PATCH 12/16] Return error when private sharing doesn't exist Change-Id: Ib2f79da356c9b6830afe0654e79f70b627842ec4 --- src/common/service_impl.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index a14491f..65b7bf9 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -140,6 +140,13 @@ bool isTizen2XVersion(const std::string &version) return false; } +bool sharingExists(const std::string &targetAppName, const std::string &path) +{ + int targetPathCount; + PrivilegeDb::getInstance().GetTargetPathSharingCount(targetAppName, path, targetPathCount); + return targetPathCount != 0; +} + class ScopedTransaction { public: ScopedTransaction() : m_isCommited(false) { @@ -1297,6 +1304,11 @@ int ServiceImpl::dropPrivatePathSharing( } for(const auto &path : paths) { + if (!sharingExists(targetAppName, path)) { + LogError("Sharing doesn't exist: owner=" << ownerAppName + << ", target=" << targetAppName << ", path=" << path); + return SECURITY_MANAGER_ERROR_INPUT_PARAM; + } std::string pathLabel = SmackLabels::getSmackLabelFromPath(path); if (pathLabel != SmackLabels::generatePkgLabel(ownerPkgName)) { std::string generatedPathLabel = SmackLabels::generateSharedPrivateLabel(ownerPkgName, path); -- 2.7.4 From 19d63b5da01410d5f79d34ef2d4e62e1a63468b1 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 26 Feb 2016 17:08:51 +0100 Subject: [PATCH 13/16] PrivilegeDB: Add getters for fetching owner/target private sharing Add getter functions to privilege db to fetch sharing info for specified owner application or specified target application. These are required to properly drop rules on application uninstallation. Change-Id: I7ea9933d65f453cf8838c519759be9a4036dacb9 --- src/common/include/privilege_db.h | 24 ++++++++++++++++++++++++ src/common/privilege_db.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/common/include/privilege_db.h b/src/common/include/privilege_db.h index c6b794a..a14038a 100644 --- a/src/common/include/privilege_db.h +++ b/src/common/include/privilege_db.h @@ -62,6 +62,8 @@ enum class StmtType { EAddPrivatePathSharing, ERemovePrivatePathSharing, EGetAllSharedPaths, + EGetSharingForOwner, + EGetSharingForTarget, EClearSharing, EClearPrivatePaths, EGetPrivilegeGroups, @@ -117,6 +119,8 @@ private: { StmtType::EAddPrivatePathSharing, "INSERT INTO app_private_sharing_view(owner_app_name, target_app_name, path, path_label) VALUES(?, ?, ?, ?)"}, { StmtType::ERemovePrivatePathSharing, "DELETE FROM app_private_sharing_view WHERE owner_app_name = ? AND target_app_name = ? AND path = ?"}, { StmtType::EGetAllSharedPaths, "SELECT owner_app_name, path FROM app_private_sharing_view ORDER BY owner_app_name"}, + { StmtType::EGetSharingForOwner, "SELECT target_app_name, path FROM app_private_sharing_view WHERE owner_app_name = ?"}, + { StmtType::EGetSharingForTarget, "SELECT owner_app_name, path FROM app_private_sharing_view WHERE target_app_name = ?"}, { StmtType::EClearSharing, "DELETE FROM app_private_sharing;"}, { StmtType::EClearPrivatePaths, "DELETE FROM shared_path;"}, { StmtType::EGetPrivilegeGroups, " SELECT group_name FROM privilege_group_view WHERE privilege_name = ?" }, @@ -392,6 +396,26 @@ public: void GetAllPrivateSharing(std::map> &appPathMap); /** + * Get all paths shared with target applications by specified owner application + * + * @param ownerAppName - owner of queried sharings + * @param ownerSharing - map containing vectors of paths shared by specified application + * mapped by target application names + * @exception DB::SqlConnection::Exception::InternalError on internal error + */ + void GetPrivateSharingForOwner(const std::string &ownerAppName, + std::map> &ownerSharing); + /** + * Get all paths shared with specified target application name + * + * @param targetAppName - target of queried sharings + * @param targetSharing - map containing vectors of paths shared with specified application + * mapped by owner application names + * @exception DB::SqlConnection::Exception::InternalError on internal error + */ + void GetPrivateSharingForTarget(const std::string &targetAppName, + std::map> &targetSharing); + /** * Clear information about private sharing. * * @exception DB::SqlConnection::Exception::InternalError on internal error diff --git a/src/common/privilege_db.cpp b/src/common/privilege_db.cpp index 54bc75a..70da867 100644 --- a/src/common/privilege_db.cpp +++ b/src/common/privilege_db.cpp @@ -324,6 +324,36 @@ void PrivilegeDb::GetAllPrivateSharing(std::map> &ownerSharing) +{ + try_catch([&] { + auto command = getStatement(StmtType::EGetSharingForOwner); + command->BindString(1, ownerAppName); + while (command->Step()) { + std::string targetAppName = command->GetColumnString(0); + std::string path = command->GetColumnString(1); + LogDebug("Got appName : " << targetAppName << " and path label : " << path); + ownerSharing[targetAppName].push_back(path); + } + }); +} + +void PrivilegeDb::GetPrivateSharingForTarget(const std::string &targetAppName, + std::map> &targetSharing) +{ + try_catch([&] { + auto command = getStatement(StmtType::EGetSharingForTarget); + command->BindString(1, targetAppName); + while (command->Step()) { + std::string ownerAppName = command->GetColumnString(0); + std::string path = command->GetColumnString(1); + LogDebug("Got appName : " << ownerAppName << " and path label : " << path); + targetSharing[ownerAppName].push_back(path); + } + }); +} + void PrivilegeDb::ClearPrivateSharing() { try_catch([&] { { -- 2.7.4 From 32519340eae40624ca8152c8a2cdb2edbe78dd78 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 18 May 2016 10:02:22 +0200 Subject: [PATCH 14/16] PrivilegeDB: Add private sharing squashing Squash specific private sharing so counter is set to 1. This makes it easier to remove private sharing for uninstalled applications. Change-Id: Ide7360d4381ffa26492a176fe1d2d64247b22d31 --- db/db.sql | 12 +++++++++++- db/updates/update-db-to-v4.sql | 5 +++++ src/common/include/privilege_db.h | 13 +++++++++++++ src/common/privilege_db.cpp | 10 ++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 db/updates/update-db-to-v4.sql diff --git a/db/db.sql b/db/db.sql index 7778a39..fd3200e 100644 --- a/db/db.sql +++ b/db/db.sql @@ -4,7 +4,7 @@ PRAGMA auto_vacuum = NONE; BEGIN EXCLUSIVE TRANSACTION; -PRAGMA user_version = 3; +PRAGMA user_version = 4; CREATE TABLE IF NOT EXISTS pkg ( pkg_id INTEGER PRIMARY KEY, @@ -172,6 +172,16 @@ BEGIN 0) + 1); END; +DROP TRIGGER IF EXISTS app_private_sharing_view_update_trigger; +CREATE TRIGGER app_private_sharing_view_update_trigger +INSTEAD OF UPDATE OF counter ON app_private_sharing_view +BEGIN + UPDATE app_private_sharing + SET counter = NEW.counter + WHERE target_app_name = OLD.target_app_name + AND path_id = (SELECT path_id FROM shared_path WHERE path = OLD.path); +END; + DROP TRIGGER IF EXISTS app_private_sharing_view_remove_delete_trigger; CREATE TRIGGER app_private_sharing_view_remove_delete_trigger INSTEAD OF DELETE ON app_private_sharing_view diff --git a/db/updates/update-db-to-v4.sql b/db/updates/update-db-to-v4.sql new file mode 100644 index 0000000..29f65b9 --- /dev/null +++ b/db/updates/update-db-to-v4.sql @@ -0,0 +1,5 @@ +BEGIN EXCLUSIVE TRANSACTION; + +PRAGMA user_version = 4; + +COMMIT TRANSACTION; diff --git a/src/common/include/privilege_db.h b/src/common/include/privilege_db.h index a14038a..043317a 100644 --- a/src/common/include/privilege_db.h +++ b/src/common/include/privilege_db.h @@ -64,6 +64,7 @@ enum class StmtType { EGetAllSharedPaths, EGetSharingForOwner, EGetSharingForTarget, + ESquashSharing, EClearSharing, EClearPrivatePaths, EGetPrivilegeGroups, @@ -121,6 +122,7 @@ private: { StmtType::EGetAllSharedPaths, "SELECT owner_app_name, path FROM app_private_sharing_view ORDER BY owner_app_name"}, { StmtType::EGetSharingForOwner, "SELECT target_app_name, path FROM app_private_sharing_view WHERE owner_app_name = ?"}, { StmtType::EGetSharingForTarget, "SELECT owner_app_name, path FROM app_private_sharing_view WHERE target_app_name = ?"}, + { StmtType::ESquashSharing, "UPDATE app_private_sharing_view SET counter = 1 WHERE target_app_name = ? AND path = ?"}, { StmtType::EClearSharing, "DELETE FROM app_private_sharing;"}, { StmtType::EClearPrivatePaths, "DELETE FROM shared_path;"}, { StmtType::EGetPrivilegeGroups, " SELECT group_name FROM privilege_group_view WHERE privilege_name = ?" }, @@ -415,6 +417,17 @@ public: */ void GetPrivateSharingForTarget(const std::string &targetAppName, std::map> &targetSharing); + + /** + * Change sharing counter to 1. + * + * @param targetAppName - target application name + * @param path - path name + * + * @exception DB::SqlConnection::Exception::InternalError on internal error + */ + void SquashSharing(const std::string &targetAppName, const std::string &path); + /** * Clear information about private sharing. * diff --git a/src/common/privilege_db.cpp b/src/common/privilege_db.cpp index 70da867..016c22a 100644 --- a/src/common/privilege_db.cpp +++ b/src/common/privilege_db.cpp @@ -354,6 +354,16 @@ void PrivilegeDb::GetPrivateSharingForTarget(const std::string &targetAppName, }); } +void PrivilegeDb::SquashSharing(const std::string &targetAppName, const std::string &path) { + try_catch([&] { + auto command = getStatement(StmtType::ESquashSharing); + command->BindString(1, targetAppName); + command->BindString(2, path); + + command->Step(); + }); +} + void PrivilegeDb::ClearPrivateSharing() { try_catch([&] { { -- 2.7.4 From a8c0160a0d5b52acca6a4274ea2f09db4cf00c90 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 15 Jun 2016 16:10:14 +0200 Subject: [PATCH 15/16] ServiceImpl: remove sharing rules on application uninstall Drop all related private sharing to uninstalled application (where it appears as owner application or target application). Change-Id: I3b9b73f325486c5463b6a38be23d0bad2bce5399 --- src/common/include/service_impl.h | 4 ++++ src/common/service_impl.cpp | 48 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index 652244a..2b0a6fa 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -74,6 +74,10 @@ private: static bool isPrivilegePrivacy(const std::string &privilege); + int squashDropPrivateSharing(const std::string &ownerAppName, + const std::string &targetAppName, + const std::string &path); + int dropOnePrivateSharing(const std::string &ownerAppName, const std::string &ownerPkgName, const std::vector &ownerPkgContents, diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 65b7bf9..2016607 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,11 @@ bool sharingExists(const std::string &targetAppName, const std::string &path) return targetPathCount != 0; } +bool fileExists(const std::string &path) { + struct stat buffer; + return (stat(path.c_str(), &buffer) == 0) && S_ISREG(buffer.st_mode); +} + class ScopedTransaction { public: ScopedTransaction() : m_isCommited(false) { @@ -544,6 +550,8 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) bool removeAuthor = false; std::string cynaraUserStr; SmackRules::PkgsApps tizen2XpkgsApps; + std::map> asOwnerSharing; + std::map> asTargetSharing; int authorId; installRequestMangle(req, cynaraUserStr); @@ -579,14 +587,47 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents); PrivilegeDb::getInstance().GetAppVersion(req.appName, req.tizenVersion); PrivilegeDb::getInstance().UpdateAppPrivileges(req.appName, req.uid, std::vector()); - PrivilegeDb::getInstance().RemoveApplication(req.appName, req.uid, removeApp, removePkg, removeAuthor); + PrivilegeDb::getInstance().GetPrivateSharingForOwner(req.appName, asOwnerSharing); + PrivilegeDb::getInstance().GetPrivateSharingForTarget(req.appName, asTargetSharing); // if uninstalled app is targetted to Tizen 2.X, remove other 2.X apps RO rules it's shared dir if (isTizen2XVersion(req.tizenVersion)) getTizen2XApps(tizen2XpkgsApps); - CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector(), isPrivilegePrivacy); + for (const auto &targetPathsInfo : asOwnerSharing) { + const auto &targetAppName = targetPathsInfo.first; + const auto &paths = targetPathsInfo.second; + // Squash sharing - change counter to 1, so dropPrivatePathSharing will completely clean it + for (const auto &path : paths) { + PrivilegeDb::getInstance().SquashSharing(targetAppName, path); + int ret = dropOnePrivateSharing(req.appName, req.pkgName, pkgContents, targetAppName, path); + if (ret != SECURITY_MANAGER_SUCCESS) { + //Ignore error, we want to drop as much as we can + LogError("Couldn't drop sharing between " << req.appName << " and " << targetAppName); + } + } + } + for (const auto &ownerPathsInfo : asTargetSharing) { + const auto &ownerAppName = ownerPathsInfo.first; + const auto &paths = ownerPathsInfo.second; + // Squash sharing - change counter to 1, so dropPrivatePathSharing will completely clean it + std::string ownerPkgName; + std::vector ownerPkgContents; + PrivilegeDb::getInstance().GetAppPkgName(ownerAppName, ownerPkgName); + PrivilegeDb::getInstance().GetPkgApps(ownerPkgName, ownerPkgContents); + for (const auto &path : paths) { + PrivilegeDb::getInstance().SquashSharing(req.appName, path); + int ret = dropOnePrivateSharing(ownerAppName, ownerPkgName, ownerPkgContents, req.appName, path); + if (ret != SECURITY_MANAGER_SUCCESS) { + //Ignore error, we want to drop as much as we can + LogError("Couldn't drop sharing between " << req.appName << " and " << ownerAppName); + } + } + } + + PrivilegeDb::getInstance().RemoveApplication(req.appName, req.uid, removeApp, removePkg, removeAuthor); + CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector(), isPrivilegePrivacy); PrivilegeDb::getInstance().CommitTransaction(); LogDebug("Application uninstallation commited to database"); PermissibleSet::updatePermissibleFile(req.uid, req.installationType); @@ -1152,7 +1193,8 @@ int ServiceImpl::dropOnePrivateSharing( if (targetPathCount > 0) { return SECURITY_MANAGER_SUCCESS; } - if (pathCount < 1) { + //This function can be also called when application is uninstalled, so path won't exist + if (pathCount < 1 && fileExists(path)) { SmackLabels::setupPath(ownerPkgName, path, SECURITY_MANAGER_PATH_RW); } std::string pathLabel = SmackLabels::generateSharedPrivateLabel(ownerPkgName, path); -- 2.7.4 From f9622bb8d2e8e44815c117c44fb4a4751547c513 Mon Sep 17 00:00:00 2001 From: Yunjin Lee Date: Mon, 13 Jun 2016 17:13:16 +0900 Subject: [PATCH 16/16] Add internal privilege for web only privilege Some web APIs are not a wrapper of native API so web privileges for those have no mapping native privilege. They all are mapped to http://tizen.org/privilege/notexist now so web application with one of those privilege can get access to other web only privilged APIs. Therefore we add internal privileges for them to check the permission properly. (format of http://tizen.org/privilege/internal/web/xxxx) If web privilege name is http://tizen.org/privilege/websetting then mapping internal privilege name is http://tizen.org/privilege/internal/web/websetting. Change-Id: I8385fa80c17e2b830c944aaa07c6ea3e5758b898 Signed-off-by: Yunjin Lee --- policy/usertype-admin.profile | 10 ++++++++++ policy/usertype-guest.profile | 10 ++++++++++ policy/usertype-normal.profile | 10 ++++++++++ policy/usertype-system.profile | 10 ++++++++++ 4 files changed, 40 insertions(+) diff --git a/policy/usertype-admin.profile b/policy/usertype-admin.profile index 0f4972e..214ee8d 100644 --- a/policy/usertype-admin.profile +++ b/policy/usertype-admin.profile @@ -119,3 +119,13 @@ * http://tizen.org/privilege/internal/inputdevice.block * http://tizen.org/privilege/internal/usermanagement * http://tizen.org/privilege/internal/appdebugging +* http://tizen.org/privilege/internal/web/appmanager.certificate +* http://tizen.org/privilege/internal/web/datasync +* http://tizen.org/privilege/internal/web/fullscreen +* http://tizen.org/privilege/internal/web/tv.audio +* http://tizen.org/privilege/internal/web/tv.channel +* http://tizen.org/privilege/internal/web/tv.display +* http://tizen.org/privilege/internal/web/tv.inputdevice +* http://tizen.org/privilege/internal/web/tv.window +* http://tizen.org/privilege/internal/web/unlimitedstorage +* http://tizen.org/privilege/internal/web/websetting diff --git a/policy/usertype-guest.profile b/policy/usertype-guest.profile index fdfd620..b628a67 100644 --- a/policy/usertype-guest.profile +++ b/policy/usertype-guest.profile @@ -118,3 +118,13 @@ * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block * http://tizen.org/privilege/internal/appdebugging +* http://tizen.org/privilege/internal/web/appmanager.certificate +* http://tizen.org/privilege/internal/web/datasync +* http://tizen.org/privilege/internal/web/fullscreen +* http://tizen.org/privilege/internal/web/tv.audio +* http://tizen.org/privilege/internal/web/tv.channel +* http://tizen.org/privilege/internal/web/tv.display +* http://tizen.org/privilege/internal/web/tv.inputdevice +* http://tizen.org/privilege/internal/web/tv.window +* http://tizen.org/privilege/internal/web/unlimitedstorage +* http://tizen.org/privilege/internal/web/websetting diff --git a/policy/usertype-normal.profile b/policy/usertype-normal.profile index e144020..15e1f0d 100644 --- a/policy/usertype-normal.profile +++ b/policy/usertype-normal.profile @@ -118,3 +118,13 @@ * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block * http://tizen.org/privilege/internal/appdebugging +* http://tizen.org/privilege/internal/web/appmanager.certificate +* http://tizen.org/privilege/internal/web/datasync +* http://tizen.org/privilege/internal/web/fullscreen +* http://tizen.org/privilege/internal/web/tv.audio +* http://tizen.org/privilege/internal/web/tv.channel +* http://tizen.org/privilege/internal/web/tv.display +* http://tizen.org/privilege/internal/web/tv.inputdevice +* http://tizen.org/privilege/internal/web/tv.window +* http://tizen.org/privilege/internal/web/unlimitedstorage +* http://tizen.org/privilege/internal/web/websetting diff --git a/policy/usertype-system.profile b/policy/usertype-system.profile index 0af9203..af2ceec 100644 --- a/policy/usertype-system.profile +++ b/policy/usertype-system.profile @@ -118,3 +118,13 @@ * http://tizen.org/privilege/internal/dbus * http://tizen.org/privilege/internal/inputdevice.block * http://tizen.org/privilege/internal/appdebugging +* http://tizen.org/privilege/internal/web/appmanager.certificate +* http://tizen.org/privilege/internal/web/datasync +* http://tizen.org/privilege/internal/web/fullscreen +* http://tizen.org/privilege/internal/web/tv.audio +* http://tizen.org/privilege/internal/web/tv.channel +* http://tizen.org/privilege/internal/web/tv.display +* http://tizen.org/privilege/internal/web/tv.inputdevice +* http://tizen.org/privilege/internal/web/tv.window +* http://tizen.org/privilege/internal/web/unlimitedstorage +* http://tizen.org/privilege/internal/web/websetting -- 2.7.4