diff options
author | Zofia Abramowska <z.abramowska@samsung.com> | 2016-09-08 18:29:45 +0200 |
---|---|---|
committer | Rafal Krypa <r.krypa@samsung.com> | 2016-09-28 18:13:09 +0200 |
commit | 5b9adf81b4bba82e9a6ace62bc3ac43f6e873519 (patch) | |
tree | 93934a5258e601017348c75d160fc52aacde2f40 | |
parent | e831af8e2928a20d2a46b74ffdbd0e0e046cee03 (diff) | |
download | security-manager-5b9adf81b4bba82e9a6ace62bc3ac43f6e873519.tar.gz security-manager-5b9adf81b4bba82e9a6ace62bc3ac43f6e873519.tar.bz2 security-manager-5b9adf81b4bba82e9a6ace62bc3ac43f6e873519.zip |
Change the way of app process label generation
Application process label depends on isHybrid flag, if flag
value is:
* 0 - all applications in package has the same process label:
"User::Pkg::pkg_id"
* 1 - each application in package has different process label:
"User::Pkg::pkg_id::App::app_Id"
Due to this change, app identifying API changes its behaviour:
for hybrid applications both app_id and pkg_id are returned,
for non-hybrid applications only pkg_id is returned.
From now on identyfing particular application is not always
possible.
Change-Id: Ice62b03be632524ec452569b6c8419f357db1b7f
-rw-r--r-- | src/client/client-security-manager.cpp | 15 | ||||
-rw-r--r-- | src/common/include/smack-labels.h | 4 | ||||
-rw-r--r-- | src/common/service_impl.cpp | 97 | ||||
-rw-r--r-- | src/common/smack-labels.cpp | 35 | ||||
-rw-r--r-- | src/include/app-runtime.h | 7 |
5 files changed, 112 insertions, 46 deletions
diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 5f30c203..30b631a5 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -1295,21 +1295,24 @@ static lib_retcode get_app_and_pkg_id_from_smack_label( char **pkg_name, char **app_name) { - std::string appNameString; - + std::string appNameString, pkgNameString; try { - appNameString = SmackLabels::generateAppNameFromLabel(label); + + SmackLabels::generateAppPkgNameFromLabel(label, appNameString, pkgNameString); } catch (const SmackException::InvalidLabel &) { return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT; } - if (app_name && !(*app_name = strdup(appNameString.c_str()))) { + if (app_name && !appNameString.empty() && !(*app_name = strdup(appNameString.c_str()))) { LogError("Memory allocation in strdup failed."); return SECURITY_MANAGER_ERROR_MEMORY; } - return pkg_name ? static_cast<lib_retcode>(security_manager_get_app_pkgid(pkg_name, appNameString.c_str())) - : SECURITY_MANAGER_SUCCESS; + if (pkg_name && !(*pkg_name = strdup(pkgNameString.c_str()))) { + LogError("Memory allocation in strdup failed."); + return SECURITY_MANAGER_ERROR_MEMORY; + } + return SECURITY_MANAGER_SUCCESS; } static int security_manager_identify_app( diff --git a/src/common/include/smack-labels.h b/src/common/include/smack-labels.h index 213e4068..9ad95b96 100644 --- a/src/common/include/smack-labels.h +++ b/src/common/include/smack-labels.h @@ -67,9 +67,11 @@ void setupSharedPrivatePath(const std::string &pkgName, const std::string &path) * Generates application name for a label fetched from Cynara * * @param[in] label string to fetch application name for + * @param[out] appName application identifier (can be empty if label belongs to non-hybrid app) + * @param[out] pkgName package identifier (cannot be empty) * @return application name on success, empty string on error. */ -std::string generateAppNameFromLabel(const std::string &label); +void generateAppPkgNameFromLabel(const std::string &label, std::string &appName, std::string &pkgName); /** * Generates label for an application identifier diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 79fc050c..72d97244 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -70,6 +70,10 @@ static std::string getAppProcessLabel(const std::string &appName) { std::string pkgName; PrivilegeDb::getInstance().GetAppPkgName(appName, pkgName); + if (pkgName.empty()) { + LogWarning("Cannot create label for unknown application: " << appName); + return ""; + } return getAppProcessLabel(appName, pkgName); } @@ -138,9 +142,19 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr, if (!policyEntry.privilege.compare(SECURITY_MANAGER_ANY)) policyEntry.privilege = CYNARA_ADMIN_WILDCARD; + std::string cynaraClient; + if (policyEntry.appName.compare(SECURITY_MANAGER_ANY)) { + cynaraClient = getAppProcessLabel(policyEntry.appName); + if (cynaraClient.empty()) { + LogWarning("Cannot set policy for unknown application " << policyEntry.appName); + return SECURITY_MANAGER_ERROR_APP_UNKNOWN; + } + } else { + cynaraClient = CYNARA_ADMIN_WILDCARD; + } + cyap = std::move(CynaraAdminPolicy( - policyEntry.appName.compare(SECURITY_MANAGER_ANY) ? - getAppProcessLabel(policyEntry.appName) : CYNARA_ADMIN_WILDCARD, + cynaraClient, policyEntry.user, policyEntry.privilege, level, @@ -633,6 +647,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) std::map<std::string, std::vector<std::string>> asOwnerSharing; std::map<std::string, std::vector<std::string>> asTargetSharing; int authorId; + bool isPkgHybrid; installRequestMangle(req, cynaraUserStr); @@ -656,6 +671,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) return SECURITY_MANAGER_SUCCESS; } + isPkgHybrid = PrivilegeDb::getInstance().IsPackageHybrid(req.pkgName); processLabel = getAppProcessLabel(req.appName, req.pkgName); LogDebug("Generated uninstall parameters: pkgName=" << req.pkgName << " Smack label=" << processLabel); @@ -741,7 +757,13 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) try { if (removeApp) { LogDebug("Removing Smack rules for appName " << req.appName); - SmackRules::uninstallApplicationRules(req.appName, processLabel); + if (isPkgHybrid || removePkg) { + /* + * Nonhybrid apps have the same label, so revoking it is unnecessary + * unless whole packagee is being removed. + */ + SmackRules::uninstallApplicationRules(req.appName, processLabel); + } LogDebug("Removing Smack rules for pkgName " << req.pkgName); SmackRules::uninstallPackageRules(req.pkgName); if (!removePkg) { @@ -753,7 +775,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) SmackRules::generateSharedRORules(pkgsProcessLabels, sharedROPkgs); if (removePkg) - SmackRules::revokeSharedRORules(pkgsProcessLabels, req.pkgName); + SmackRules::revokeSharedRORules(pkgsProcessLabels, req.pkgName); } if (authorId != -1 && removeAuthor) { @@ -1058,32 +1080,57 @@ int ServiceImpl::getConfiguredPolicy(const Credentials &creds, bool forAdmin, continue; policy_entry pe; - - pe.appName = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? SmackLabels::generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY; - pe.user = strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY; - pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY; - pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result); - - if (!forAdmin) { - // All policy entries in PRIVACY_MANAGER should be fully-qualified - pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription( - CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel( - policy.client, policy.user, policy.privilege)); + std::vector<std::string> appNames; + std::string appName, pkgName; + + if (strcmp(policy.client, CYNARA_ADMIN_WILDCARD)) { + SmackLabels::generateAppPkgNameFromLabel(policy.client, appName, pkgName); + if (!appName.empty()) { + // Hybrid app + appNames.push_back(appName); + } else { + if (filter.appName == SECURITY_MANAGER_ANY) { + // If user requested policy for all apps, we have to demangle pkgName to + // set of appNames in case of non-hybrid apps + PrivilegeDb::getInstance().GetPkgApps(pkgName, appNames); + } else { + // If user requested policy for specific appName, we have to copy + // appName from filter for non-hybrid apps + appNames.push_back(filter.appName); + } + } } else { - // Cannot reliably calculate maxLavel for policies from ADMIN bucket - pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(CYNARA_ADMIN_ALLOW); + // Cynara wildcard -> SM any + appNames.push_back(SECURITY_MANAGER_ANY); } + for (const auto &app : appNames) { + pe.appName = app; + pe.user = strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY; + pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY; + pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result); - LogDebug( - "[policy_entry] app: " << pe.appName - << " user: " << pe.user - << " privilege: " << pe.privilege - << " current: " << pe.currentLevel - << " max: " << pe.maxLevel - ); + if (!forAdmin) { + // All policy entries in PRIVACY_MANAGER should be fully-qualified + pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription( + CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel( + policy.client, policy.user, policy.privilege)); + } else { + // Cannot reliably calculate maxLavel for policies from ADMIN bucket + pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(CYNARA_ADMIN_ALLOW); + } - policyEntries.push_back(pe); + + LogDebug( + "[policy_entry] app: " << pe.appName + << " user: " << pe.user + << " privilege: " << pe.privilege + << " current: " << pe.currentLevel + << " max: " << pe.maxLevel + ); + + policyEntries.push_back(pe); + } }; } catch (const CynaraException::Base &e) { diff --git a/src/common/smack-labels.cpp b/src/common/smack-labels.cpp index 73c1b046..55243a8e 100644 --- a/src/common/smack-labels.cpp +++ b/src/common/smack-labels.cpp @@ -183,28 +183,35 @@ void setupSharedPrivatePath(const std::string &pkgName, const std::string &path) pathSetSmack(path.c_str(), generateSharedPrivateLabel(pkgName, path), XATTR_NAME_SMACK); } -std::string generateAppNameFromLabel(const std::string &label) +void generateAppPkgNameFromLabel(const std::string &label, std::string &appName, std::string &pkgName) { - static const char prefix[] = "User::App::"; - - if (label.compare(0, sizeof(prefix) - 1, prefix)) - ThrowMsg(SmackException::InvalidLabel, "Cannot extract appName from Smack label " << label); - - std::string ret = label.substr(sizeof(prefix) - 1); - - if (ret.size() == 0) { - ThrowMsg(SmackException::InvalidLabel, "No appName in Smack label " << label); + static const char pkgPrefix[] = "User::Pkg::"; + static const char appPrefix[] = "::App::"; + + if (label.compare(0, sizeof(pkgPrefix) - 1, pkgPrefix)) + ThrowMsg(SmackException::InvalidLabel, "Invalid application process label " << label); + + size_t pkgStartPos = sizeof(pkgPrefix) - 1; + size_t pkgEndPos = pkgName.find(appPrefix, pkgStartPos); + if (pkgEndPos != std::string::npos) { + LogDebug("Hybrid application process label"); + size_t appStartPos = pkgEndPos + sizeof(appPrefix) - 1; + appName = label.substr(appStartPos, std::string::npos); + pkgName = label.substr(pkgStartPos, pkgEndPos - pkgStartPos); + } else { + pkgName = label.substr(pkgStartPos, std::string::npos); } - return ret; + if (pkgName.empty()) + ThrowMsg(SmackException::InvalidLabel, "No pkgName in Smack label " << label); } std::string generateProcessLabel(const std::string &appName, const std::string &pkgName, bool isHybrid) { - (void)pkgName; - (void)isHybrid; - std::string label = "User::App::" + appName; + std::string label = "User::Pkg::" + pkgName; + if (isHybrid) + label += "::App::" + appName; if (smack_label_length(label.c_str()) <= 0) ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from appName " << appName); diff --git a/src/include/app-runtime.h b/src/include/app-runtime.h index 1d7028ce..133c65ad 100644 --- a/src/include/app-runtime.h +++ b/src/include/app-runtime.h @@ -133,6 +133,9 @@ void security_manager_groups_free(char **groups, size_t groups_count); * If both app_id and pkg_id are NULL then SECURITY_MANAGER_ERROR_INPUT_PARAM will be returned. * When socket descriptor is incorrect or not related to any package, this function will * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT. + * If process on the other side is a nonhybrid application, no app_id will be available. + * + * \note For non hybrid applications only package id can be returned * * \param[in] sockfd Socket descriptor of wanted application * \param[out] pkg_id Package id of the application @@ -150,10 +153,13 @@ int security_manager_identify_app_from_socket(int sockfd, char **pkg_id, char ** * If both app_id and pkg_id are NULL then SECURITY_MANAGER_ERROR_INPUT_PARAM will be returned. * When process identifier is incorrect or not related to any package, this function will * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT. + * If given process is a nonhybrid application, no app_id will be available. * * \note Caller must be able to access and read file /proc/PID/atrr/current where PID is the given * process identifier. * + * \note For non hybrid applications only package id can be returned + * * \param[in] pid Process identifier of wanted application * \param[out] pkg_id Package id of the application * \param[out] app_id Application id of the application @@ -171,6 +177,7 @@ int security_manager_identify_app_from_pid(pid_t pid, char **pkg_id, char **app_ * When process identifier is incorrect or not related to any package, this function will * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT. * + * \note For non hybrid applications only package id can be returned * * \param[in] client Application Cynara client identifier * \param[out] pkg_id Package id of the application |