From e86f23ff74d9672bc8f46602d71215cb278194f2 Mon Sep 17 00:00:00 2001 From: Tomasz Swierczek Date: Thu, 5 Apr 2018 10:44:40 +0200 Subject: [PATCH] Add caching of App/Pkg data & use faster way to retrieve this data In client side, this data needs to be retrieved only once for given client. PkgMgr is checked only from askuser-notification daemon context, otherwise AUL environment variables/AUL API is called to get data needed on client side. This optimization should reduce API call time for ppm_check by ~60% Change-Id: I5a9238113b062df551b73e3af7e52f6b13643c81 --- packaging/askuser-notification.spec | 1 + src/client/impl/ApiInterfaceImpl.cpp | 4 +- src/client/impl/ApiInterfaceImpl.h | 4 ++ src/common/CMakeLists.txt | 3 ++ src/common/policy/AppInfo.cpp | 90 +++++++++++++++++++++++++++++++++++ src/common/policy/AppInfo.h | 76 +++++++++++++++++------------ src/common/policy/PkgInfo.cpp | 81 +++++++++++++++++++++++++++++++ src/common/policy/PkgInfo.h | 83 ++++++++++++++++++-------------- src/common/policy/Policy.cpp | 19 ++++---- src/common/policy/Policy.h | 5 +- src/common/policy/PrivilegeInfo.cpp | 11 +++-- src/common/policy/PrivilegeInfo.h | 4 +- src/common/policy/PrivilegePolicy.cpp | 5 +- src/common/policy/PrivilegePolicy.h | 3 +- src/notification-daemon/Logic.cpp | 6 ++- 15 files changed, 302 insertions(+), 93 deletions(-) create mode 100644 src/common/policy/AppInfo.cpp create mode 100644 src/common/policy/PkgInfo.cpp diff --git a/packaging/askuser-notification.spec b/packaging/askuser-notification.spec index 5c2fcf5..ba04c02 100644 --- a/packaging/askuser-notification.spec +++ b/packaging/askuser-notification.spec @@ -28,6 +28,7 @@ BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-ui-efl-util) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(aul) BuildRequires: edje-bin %if !%{defined build_type} diff --git a/src/client/impl/ApiInterfaceImpl.cpp b/src/client/impl/ApiInterfaceImpl.cpp index c653312..16e6651 100644 --- a/src/client/impl/ApiInterfaceImpl.cpp +++ b/src/client/impl/ApiInterfaceImpl.cpp @@ -99,9 +99,9 @@ int ApiInterfaceImpl::process(int fd, int events) askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privilege) { - std::string appId = getOwnAppId(); + std::string appId = getOwnAppId(m_pkgInfo); PrivilegePolicy privPolicy(appId, privilege); - auto policyLevel = privPolicy.calculatePolicy(); + auto policyLevel = privPolicy.calculatePolicy(m_appInfo); if (policyLevel == "Allow") { return ASKUSER_CHECK_RESULT_ALLOW; diff --git a/src/client/impl/ApiInterfaceImpl.h b/src/client/impl/ApiInterfaceImpl.h index 40e8d48..34e5cee 100644 --- a/src/client/impl/ApiInterfaceImpl.h +++ b/src/client/impl/ApiInterfaceImpl.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -68,6 +70,8 @@ private: StatusCallbackClosure m_statusClosure; std::unique_ptr m_channel; std::vector m_requests; + AulAppInfo m_appInfo; + AulPkgInfo m_pkgInfo; }; } // namespace Client diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b43a147..095e69f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -21,6 +21,7 @@ PKG_CHECK_MODULES(COMMON_DEP security-manager pkgmgr-info security-privilege-manager + aul ) SET(ASKUSER_COMMON_VERSION_MAJOR 0) @@ -38,6 +39,8 @@ INCLUDE_DIRECTORIES( SET(COMMON_SOURCES ${COMMON_PATH}/log/alog.cpp + ${COMMON_PATH}/policy/AppInfo.cpp + ${COMMON_PATH}/policy/PkgInfo.cpp ${COMMON_PATH}/policy/Policy.cpp ${COMMON_PATH}/policy/PrivilegeInfo.cpp ${COMMON_PATH}/policy/PrivilegePolicy.cpp diff --git a/src/common/policy/AppInfo.cpp b/src/common/policy/AppInfo.cpp new file mode 100644 index 0000000..b1d9998 --- /dev/null +++ b/src/common/policy/AppInfo.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co. + * + * 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 src/common/policy/AppInfo.cpp + * @author Tomasz Swierczek + * @brief Implementation of AppInfo (sub)classes + */ + +#include "AppInfo.h" + +#include + +#include + + +namespace AskUser { + +void AulAppInfo::fetch(const std::string &appId, uid_t uid) { + static const char *AUL_APP_TYPE = "RUNTIME_TYPE"; + static const char *AUL_TIZEN_API_VERSION = "TIZEN_API_VERSION"; + + char *type = getenv(AUL_APP_TYPE); + char *version = getenv(AUL_TIZEN_API_VERSION); + if (type) { + m_type = type; + ALOGD("aul fetched app type for appId " << appId << " is " << m_type); + } else { + ALOGE("couldn't fetch app type for appId " << appId << " with getenv from key " << AUL_APP_TYPE); + } + + if (version) { + m_version = version; + ALOGD("aul fetched app Tizen target version for appId " << appId << " is " << m_version); + } else { + ALOGE("couldn't fetch app Tizen target version for appId " << appId << " with getenv from key " << AUL_TIZEN_API_VERSION); + } + + m_appId = appId; + m_uid = uid; +} + + +void PkgMgrAppInfo::fetch(const std::string &appId, uid_t uid) { + pkgmgrinfo_appinfo_h handle = nullptr; + int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appId.c_str(), uid, &handle); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_appinfo_get_usr_appinfo failed for " << appId << " with " << ret); + return; + } + + char *type = nullptr; + ret = pkgmgrinfo_appinfo_get_apptype(handle, &type); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_appinfo_get_apptype failed with " << ret); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + return; + } + if (type) + m_type = type; + + char *version = nullptr; + ret = pkgmgrinfo_appinfo_get_api_version(handle, &version); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_appinfo_get_api_version failed with " << ret); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + return; + } + if (version) + m_version = version; + + pkgmgrinfo_appinfo_destroy_appinfo(handle); + + m_appId = appId; + m_uid = uid; +} + +} // namespace AskUser diff --git a/src/common/policy/AppInfo.h b/src/common/policy/AppInfo.h index 68cf4ab..7668596 100644 --- a/src/common/policy/AppInfo.h +++ b/src/common/policy/AppInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co. + * Copyright (c) 2017-2018 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,52 +16,66 @@ /** * @file src/common/policy/AppInfo.h * @author Zofia Abramowska - * @brief Definition of pkgmgr-info wrappers + * @author Tomasz Swierczek + * @brief Definition of app-data wrapper/cache (sub)classes */ #pragma once #include #include -#include - -#include namespace AskUser { -struct AppInfo { - AppInfo(const std::string &appId, uid_t uid) : m_handle(nullptr) { - int ret = pkgmgrinfo_appinfo_get_usr_appinfo(appId.c_str(), uid, &m_handle); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_appinfo_get_usr_appinfo failed for " << appId << " with " << ret); - m_handle = nullptr; - } +class AppInfo { +public: + + AppInfo() : m_uid(0) {}; + + virtual ~AppInfo() {}; + + virtual void purgeCache() { + m_appId.clear(); + m_type.clear(); + m_version.clear(); + m_uid = 0; } - ~AppInfo() { - if (m_handle) - pkgmgrinfo_appinfo_destroy_appinfo(m_handle); + + virtual std::string type(const std::string &appId, uid_t uid) { + update(appId, uid); + return m_type; } - const std::string type() { - char *type = nullptr; - int ret = pkgmgrinfo_appinfo_get_apptype(m_handle, &type); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_appinfo_get_apptype failed with " << ret); - return ""; - } - return type ? type : ""; + + virtual std::string apiVersion(const std::string &appId, uid_t uid) { + update(appId, uid); + return m_version; } - const std::string apiVersion() { - char *version = nullptr; - int ret = pkgmgrinfo_appinfo_get_api_version(m_handle, &version); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_appinfo_get_api_version failed with " << ret); - return ""; +protected: + virtual void fetch(const std::string &appId, uid_t uid) = 0; + + virtual void update(const std::string &appId, uid_t uid) { + if (m_appId != appId || uid != m_uid) { + purgeCache(); + fetch(appId, uid); } - return version ? version : ""; } - pkgmgrinfo_appinfo_h m_handle; + std::string m_appId; + uid_t m_uid; + std::string m_type; + std::string m_version; +}; + +class AulAppInfo : public AppInfo { +protected: + virtual void fetch(const std::string &appId, uid_t uid); }; +class PkgMgrAppInfo : public AppInfo { +protected: + virtual void fetch(const std::string &appId, uid_t uid); +}; + + } // namespace AskUser diff --git a/src/common/policy/PkgInfo.cpp b/src/common/policy/PkgInfo.cpp new file mode 100644 index 0000000..5773623 --- /dev/null +++ b/src/common/policy/PkgInfo.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co. + * + * 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 src/common/policy/PkgInfo.cpp + * @author Tomasz Swierczek + * @brief Implementation of PkgInfo (sub)classes + */ + +#include "PkgInfo.h" + +#include +#include + +#include + +namespace AskUser { + +void AulPkgInfo::fetch(const std::string &pkgId, uid_t uid) { + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + int ret = aul_app_get_appid_bypid(getpid(), buffer, sizeof(buffer) - 1); + if (AUL_R_OK == ret) + m_mainAppId = std::string(buffer); + else + ALOGE("aul_app_get_appid_bypid failed"); + + ret = aul_app_get_pkgname_bypid(getpid(), buffer, sizeof(buffer)); + if (AUL_R_OK == ret) + m_pkgLabel = std::string(buffer); + else + ALOGE("aul_app_get_pkgname_bypid failed"); + m_pkgId = pkgId; + m_uid = uid; +} + +void PkgMgrPkgInfo::fetch(const std::string &pkgId, uid_t uid) { + pkgmgrinfo_pkginfo_h handle = nullptr; + int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_pkginfo_get_usr_pkginfo failed for " << pkgId << " with " << ret); + return; + } + char *mainAppId; + ret = pkgmgrinfo_pkginfo_get_mainappid(handle, &mainAppId); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_pkginfo_get_mainappid failed with " << ret); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return; + } + if (mainAppId) + m_mainAppId = mainAppId; + + char *pkgLabel; + ret = pkgmgrinfo_pkginfo_get_label(handle, &pkgLabel); + if (ret != PMINFO_R_OK) { + ALOGE("pkgmgrinfo_pkginfo_get_label failed with " << ret); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return; + } + if (pkgLabel) + m_pkgLabel = pkgLabel; + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + m_pkgId = pkgId; + m_uid = uid; +} + +} // namespace AskUser diff --git a/src/common/policy/PkgInfo.h b/src/common/policy/PkgInfo.h index e2f9e59..c838ec9 100644 --- a/src/common/policy/PkgInfo.h +++ b/src/common/policy/PkgInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co. + * Copyright (c) 2017-2018 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,52 +16,63 @@ /** * @file src/common/policy/PkgInfo.h * @author Zofia Abramowska - * @brief Definition of pkgmgr-info wrappers + * @author Tomasz Swierczek + * @brief Definition of package-data wrappers/cache (sub)classes */ #pragma once #include #include -#include -#include +namespace AskUser { -struct PkgInfo { - PkgInfo(const std::string &pkgId, uid_t uid) : m_handle(nullptr) { - int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &m_handle); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_pkginfo_get_usr_pkginfo failed for " << pkgId << " with " << ret); - m_handle = nullptr; - } +class PkgInfo { +public: + PkgInfo() : m_uid(0) {}; + virtual ~PkgInfo() {}; + + virtual void purgeCache() { + m_pkgId.clear(); + m_mainAppId.clear(); + m_pkgLabel.clear(); + m_uid = 0; } - ~PkgInfo() { - if (m_handle) - pkgmgrinfo_pkginfo_destroy_pkginfo(m_handle); + + std::string mainAppId(const std::string &pkgId, uid_t uid) { + update(pkgId, uid); + return m_mainAppId; } - const std::string mainAppId(){ - if (!m_handle) { - return ""; - } - char *mainAppId; - int ret = pkgmgrinfo_pkginfo_get_mainappid(m_handle, &mainAppId); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_pkginfo_get_mainappid failed with " << ret); - return ""; - } - return mainAppId ? mainAppId : ""; + + std::string pkgLabel(const std::string &pkgId, uid_t uid) { + update(pkgId, uid); + return m_pkgLabel; } - const std::string pkgLabel() { - if (!m_handle) { - return ""; - } - char *pkgLabel; - int ret = pkgmgrinfo_pkginfo_get_label(m_handle, &pkgLabel); - if (ret != PMINFO_R_OK) { - ALOGE("pkgmgrinfo_pkginfo_get_label failed with " << ret); - return ""; + +protected: + virtual void fetch(const std::string &pkgId, uid_t uid) = 0; + + virtual void update(const std::string &pkgId, uid_t uid) { + if (pkgId != m_pkgId || uid != m_uid) { + purgeCache(); + fetch(pkgId, uid); } - return pkgLabel ? pkgLabel : ""; } - pkgmgrinfo_pkginfo_h m_handle; + + std::string m_pkgId; + uid_t m_uid; + std::string m_mainAppId; + std::string m_pkgLabel; +}; + +class AulPkgInfo : public PkgInfo { +protected: + virtual void fetch(const std::string &pkgId, uid_t uid); }; + +class PkgMgrPkgInfo : public PkgInfo { +protected: + virtual void fetch(const std::string &pkgId, uid_t uid); +}; + +} // namespace AskUser diff --git a/src/common/policy/Policy.cpp b/src/common/policy/Policy.cpp index 5f1954a..014871a 100644 --- a/src/common/policy/Policy.cpp +++ b/src/common/policy/Policy.cpp @@ -19,7 +19,9 @@ * @brief Implementation of Policy wrappers */ +#include #include +#include #include #include @@ -27,7 +29,6 @@ #include #include -#include "PkgInfo.h" #include "Policy.h" #include "PrivilegeInfo.h" @@ -123,7 +124,7 @@ std::vector getAppPolicy(const std::string &appId) { return fetch.fetchPolicy(); } -void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel) +void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgLabel) { char *pkgName = nullptr; char *appName = nullptr; @@ -138,16 +139,16 @@ void identifyApp(const std::string &client, std::string &appId, std::string &pkg return; } - PkgInfo pkgInfo(pkgName, geteuid()); + uid_t uid = geteuid(); if (!appName) - appId = pkgInfo.mainAppId(); + appId = pkgInfo.mainAppId(pkgName, uid); else appId = appName; - pkgLabel = pkgInfo.pkgLabel(); + pkgLabel = pkgInfo.pkgLabel(pkgName, uid); } -std::string getOwnAppId() +std::string getOwnAppId(PkgInfo &pkgInfo) { char *pkgName = nullptr; char *appName = nullptr; @@ -157,10 +158,8 @@ std::string getOwnAppId() std::unique_ptr app_name_p(appName, free); throwOnSMError("security_manager_identify_app_from_pid", ret); - if (!appName) { - PkgInfo pkgInfo(pkgName, geteuid()); - return pkgInfo.mainAppId(); - } + if (!appName) + return pkgInfo.mainAppId(pkgName, geteuid()); return appName; } diff --git a/src/common/policy/Policy.h b/src/common/policy/Policy.h index 132d067..5be4334 100644 --- a/src/common/policy/Policy.h +++ b/src/common/policy/Policy.h @@ -25,6 +25,7 @@ #include #include +#include #include struct policy_entry; @@ -34,8 +35,8 @@ namespace AskUser { class PolicyEntryCopy; -std::string getOwnAppId(); -void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel); +std::string getOwnAppId(PkgInfo &pkgInfo); +void identifyApp(PkgInfo &pkgInfo, const std::string &client, std::string &appId, std::string &pkgLabel); std::set getManifestPrivs(const std::string &appId); diff --git a/src/common/policy/PrivilegeInfo.cpp b/src/common/policy/PrivilegeInfo.cpp index 5450086..83e3ca6 100644 --- a/src/common/policy/PrivilegeInfo.cpp +++ b/src/common/policy/PrivilegeInfo.cpp @@ -22,13 +22,14 @@ #include #include #include +#include +#include #include "Policy.h" #include "PrivilegeInfo.h" #include #include -#include #include #include @@ -103,11 +104,11 @@ std::vector getPrivilegesPrivacies(const std::vector &core return std::vector(privaciesSet.begin(), privaciesSet.end()); } -std::vector getPrivilegeMapping(const std::string &appId, const Privilege &privilege) { +std::vector getPrivilegeMapping(AppInfo &appInfo, const std::string &appId, const Privilege &privilege) { ALOGD("Mapping privilege " << privilege); - AppInfo app(appId, geteuid()); - std::string version = app.apiVersion(); - std::string type = app.type(); + uid_t uid = geteuid(); + std::string version = appInfo.apiVersion(appId, uid); + std::string type = appInfo.type(appId, uid); if (version.empty() || type.empty()) { ALOGE("Failed to fetch application version and type"); diff --git a/src/common/policy/PrivilegeInfo.h b/src/common/policy/PrivilegeInfo.h index fa651bc..515a3a6 100644 --- a/src/common/policy/PrivilegeInfo.h +++ b/src/common/policy/PrivilegeInfo.h @@ -24,12 +24,14 @@ #include #include +#include #include namespace AskUser { namespace PrivilegeInfo { - std::vector getPrivilegeMapping(const std::string &appId, + std::vector getPrivilegeMapping(AppInfo &appInfo, + const std::string &appId, const Privilege &privilege); std::vector getPrivilegesPrivacies(const std::vector &corePrivileges); bool isPrivacy(const Privilege &privilege); diff --git a/src/common/policy/PrivilegePolicy.cpp b/src/common/policy/PrivilegePolicy.cpp index 66dc203..f000965 100644 --- a/src/common/policy/PrivilegePolicy.cpp +++ b/src/common/policy/PrivilegePolicy.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -73,9 +72,9 @@ PrivilegePolicy::PrivilegePolicy(const std::string &appId, const Privilege &priv m_privilege(privilege) {} -Policy PrivilegePolicy::calculatePolicy() { +Policy PrivilegePolicy::calculatePolicy(AppInfo &appInfo) { std::vector corePrivileges = - PrivilegeInfo::getPrivilegeMapping(m_appId, m_privilege); + PrivilegeInfo::getPrivilegeMapping(appInfo, m_appId, m_privilege); if (corePrivileges.empty()) { ALOGE("Privilege " << m_privilege << " doesn't map to any core privilege"); return "Deny"; diff --git a/src/common/policy/PrivilegePolicy.h b/src/common/policy/PrivilegePolicy.h index c22e45b..9f64e82 100644 --- a/src/common/policy/PrivilegePolicy.h +++ b/src/common/policy/PrivilegePolicy.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace AskUser { @@ -30,7 +31,7 @@ namespace AskUser { class PrivilegePolicy { public: PrivilegePolicy(const std::string &appId, const Privilege &privilege); - Policy calculatePolicy(); + Policy calculatePolicy(AppInfo &appInfo); std::vector getAskablePrivacies() const { return m_askablePrivacies; } diff --git a/src/notification-daemon/Logic.cpp b/src/notification-daemon/Logic.cpp index 2a47a4c..87168d5 100644 --- a/src/notification-daemon/Logic.cpp +++ b/src/notification-daemon/Logic.cpp @@ -106,7 +106,8 @@ void Logic::addChannelFd(Protocol::ConnectionFd fd, const Protocol::Credentials } std::string appId, pkgLabel; - identifyApp(creds.label, appId, pkgLabel); + PkgMgrPkgInfo pkgInfo; + identifyApp(pkgInfo, creds.label, appId, pkgLabel); ALOGD("Proper client connected"); stopTimer(); @@ -231,7 +232,8 @@ void Logic::popup(Protocol::ConnectionFd fd, Protocol::RequestId id, const std:: ConnectionInfo &conn = it->second; PrivilegePolicy privPolicy(conn.appId, privilege); - auto policyLevel = privPolicy.calculatePolicy(); + PkgMgrAppInfo appInfo; + auto policyLevel = privPolicy.calculatePolicy(appInfo); ALOGD("Privilege policy level calculated to : " << policyLevel); if (policyLevel == "Allow") { -- 2.7.4