Add security_manager_get_app_full_credentials_from_pid function 06/321306/18
authorTomasz Swierczek <t.swierczek@samsung.com>
Tue, 18 Mar 2025 14:09:01 +0000 (15:09 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 24 Apr 2025 08:14:38 +0000 (08:14 +0000)
Its meant to be a one-API-call replacement for usage of
security_manager_get_app_owner_uid & security_manager_identify_app_from_pid,
making only one round-trip to the server side.

Change-Id: I64b71dd4e6e50cf67a8106709da6f4e73918c3a7

src/client/client-security-manager.cpp
src/common/include/protocols.h
src/common/include/service_impl.h
src/common/service_impl.cpp
src/include/app-runtime.h
src/server/service/include/service.h
src/server/service/service.cpp

index c9f540e60f3e93b9360bccedc13e10e235844cea..09fb2aefe17be79eac4c95fa0cf36ec2684411f2 100644 (file)
@@ -1321,7 +1321,7 @@ static inline int security_manager_setup_namespace_internal(const MountNS::Privi
     return SECURITY_MANAGER_SUCCESS;
 }
 
-static int pidToPuid(pid_t pid, uid_t &puid)
+static int pidToUid(pid_t pid, uid_t &puid)
 {
     struct stat st;
     std::string path;
@@ -1944,7 +1944,7 @@ int security_manager_identify_app_from_pid(pid_t pid, char **pkg_name, char **ap
         }
 
         uid_t puid;
-        int ret = pidToPuid(pid, puid);
+        int ret = pidToUid(pid, puid);
         if (ret != SECURITY_MANAGER_SUCCESS) {
             LogError("Could not find a PUID for the given PID: " << pid);
             return ret;
@@ -2024,7 +2024,7 @@ int security_manager_get_app_owner_uid(pid_t pid, uid_t *uid)
         return SECURITY_MANAGER_ERROR_INPUT_PARAM;
 
     uid_t puid;
-    int ret = pidToPuid(pid, puid);
+    int ret = pidToUid(pid, puid);
     if (ret != SECURITY_MANAGER_SUCCESS) {
         LogError("Could not find a PUID for the given PID: " << pid);
         return ret;
@@ -2053,6 +2053,67 @@ int security_manager_get_app_owner_uid(pid_t pid, uid_t *uid)
     });
 }
 
+SECURITY_MANAGER_API
+int security_manager_get_app_full_credentials_from_pid(pid_t pid, uid_t *owner_uid,
+                                                       char **pkg_id, char **app_id)
+{
+    if (!owner_uid || !pkg_id || !app_id)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    uid_t puid;
+    int ret = pidToUid(pid, puid);
+    if (ret != SECURITY_MANAGER_SUCCESS) {
+        LogError("Could not find uid for given PID: " << pid);
+        return ret;
+    }
+
+    if (smack_simple_check()) {
+        // no need to call daemon at all, all in-place, reading the label & uid from /proc
+        *owner_uid = puid;
+        return security_manager_identify_app_from_pid(pid, pkg_id, app_id);
+    } else {
+        // here we need to call the daemon to get all data in one call
+        using namespace SecurityManager;
+        return try_catch([&]() -> int {
+            ClientRequest request(SecurityModuleCall::APP_GET_FULL_CREDS);
+            request.send(puid);
+            if (!request.failed()) {
+                uid_t ownerId;
+                std::string appNameString, pkgNameString;
+
+                request.recv(ownerId, appNameString, pkgNameString);
+
+                if (appNameString.empty() && pkgNameString.empty()) {
+                    LogError("Empty return from APP_GET_FULL_CREDS from server!");
+                    return SECURITY_MANAGER_ERROR_UNKNOWN;
+                }
+
+                LogInfo("Received ownerId: " << ownerId << " appName: " << appNameString << " pkgName: " << pkgNameString << " for app PID " << pid);
+
+                *owner_uid = ownerId;
+
+                char *appName = nullptr;
+                if (!appNameString.empty() &&
+                    !(appName = strdup(appNameString.c_str()))) {
+                    LogError("Memory allocation in strdup failed.");
+                    return SECURITY_MANAGER_ERROR_MEMORY;
+                }
+
+                char *pkgName = nullptr;
+
+                if (!(pkgName = strdup(pkgNameString.c_str()))) {
+                    free(appName);
+                    LogError("Memory allocation in strdup failed.");
+                    return SECURITY_MANAGER_ERROR_MEMORY;
+                }
+                *pkg_id = pkgName;
+                *app_id = appName;
+            }
+            return request.getStatus();
+        });
+    }
+}
+
 SECURITY_MANAGER_API
 int security_manager_identify_app_from_cynara_client(const char *client, char **pkg_name,
                                                      char **app_name)
index 283ce4a50158fd3a656ccc72db81c05590ef0314..4dfef7eb7c6ad2ec31d4fefb2864bda0f4a78611 100644 (file)
@@ -139,6 +139,7 @@ enum class SecurityModuleCall
     APP_GET_OWNER,
     APP_GET_PKG_NAME,
     APP_GET_PUID_AND_AGID,
+    APP_GET_FULL_CREDS,
     APP_APPLY_PRIVATE_SHARING,
     APP_DROP_PRIVATE_SHARING,
     USER_ADD,
index bc13702d8005cdbf46caf693d7209965da4ba481..b33274dbea6b9e6725fcdace13f4d6ae2cde88bc 100644 (file)
@@ -129,6 +129,19 @@ public:
     */
     int getAppOwner(pid_t pid, uid_t &ownerId);
 
+    /**
+    * Process a request to get an application's owner uid, pkgId and appId at once.
+    *
+    * @param[in] puid application process user identifier
+    * @param[in] pid application process identifier
+    * @param[out] ownerId returned application owner uid
+    * @param[out] appName returned application name
+    * @param[out] pkgName returned package name
+    *
+    * @return API return code, as defined in protocols.h
+    */
+    int getAppFullCreds(uid_t puid, pid_t pid, uid_t &ownerId, std::string &appName, std::string &pkgName);
+
     /**
     * Process package id query.
     * Retrieves the package id associated with given application id.
index edd615b092a73a2b56d79439ff49bc7d05a506d1..bb6dc61fe11c848a16ee4626a6ec2dc5431d7976 100644 (file)
@@ -1212,6 +1212,25 @@ int ServiceImpl::getAppOwner(pid_t pid, uid_t &ownerId)
     return SECURITY_MANAGER_SUCCESS;
 }
 
+int ServiceImpl::getAppFullCreds(uid_t puid, pid_t pid, uid_t &ownerId, std::string &appName, std::string &pkgName)
+{
+    try {
+        m_privilegeDb.GetAppNameAndPkg(puid, appName, pkgName);
+        if (pkgName.empty()) {
+            LogWarning("No app for PUID " <<  puid << " found in the database");
+            return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+        }
+        LogInfo("appName: " << appName << ", pkgName: " << pkgName);
+
+        return getAppOwner(pid, ownerId);
+    } catch (const PrivilegeDb::Exception::Base &e) {
+        LogError("Error while getting app credentials from database: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
 int ServiceImpl::getPkgName(const std::string &appName, std::string &pkgName)
 {
     LogDebug("appName: " << appName);
index d2a101e5eb776551dc4ab6a3429fa6b550a9116c..02a8c7124fb6b1dce9bee930212c0ef6db15186d 100644 (file)
@@ -254,6 +254,24 @@ int security_manager_get_app_owner_uid(pid_t pid, uid_t *uid);
  */
 int security_manager_identify_app_from_cynara_client(const char *client, char **pkg_id,
                                                      char **app_id);
+
+/**
+ * Returns the complete credentials of app identified with PID - this is:
+ * - UID of the app owner for which app is launched (same as from security_manager_get_app_owner_uid)
+ * - pkg_id & app_id (if its applicable) (same as from security_manager_identify_app_from_pid).
+ * pkg_id and app_id arguments are necessary (cannot be null), returned pointers have to be freed.
+ *
+ * The function is meant as a one-call replacement for above API calls (with one round-trip to daemon).
+ *
+ * \param[in]   pid process ID of application
+ * \param[out]  owner_uid the user ID of application user
+ * \param[out]  pkg_id  Package id of the application
+ * \param[out]  app_id  Application id of the application
+ * \return SECURITY_MANAGER_SUCCESS or error code
+ */
+int security_manager_get_app_full_credentials_from_pid(pid_t pid, uid_t *owner_uid,
+                                                       char **pkg_id, char **app_id);
+
 /**
  * Check whether an application would have access to a privilege
  *
index a0224c7e9f3a6f8111fb21f0db3760c5051e90f5..42c309d2876263890d117c6bffb662d33255c629 100644 (file)
@@ -130,6 +130,14 @@ private:
      */
     void processGetAppOwner(MessageBuffer &buffer, const Credentials &creds);
 
+    /**
+     * Process getting owner uid, pkgId & appId identifiers from an app puid
+     *
+     * @param buffer Input/output message buffer
+     * @param creds  credentials of the requesting process
+     */
+    void processGetAppFullCreds(MessageBuffer &buffer, const Credentials &creds);
+
     /**
      * Process getting package identifier from an app identifier
      *
index d7dd5994f73ddbe11c35a6ff466828b5c1c93dd7..8dccfe39383abda2453c42133450e8498e038464 100644 (file)
@@ -87,6 +87,10 @@ void Service::processEvent(Event &&msg)
                 LogDebug("call_type: SecurityModuleCall::APP_GET_OWNER");
                 processGetAppOwner(msg.buffer, msg.creds);
                 break;
+            case SecurityModuleCall::APP_GET_FULL_CREDS:
+                LogDebug("call_type: SecurityModuleCall::APP_GET_FULL_CREDS");
+                processGetAppFullCreds(msg.buffer, msg.creds);
+                break;
             case SecurityModuleCall::APP_GET_PKG_NAME:
                 LogDebug("call_type: SecurityModuleCall::APP_GET_PKG_NAME");
                 processGetPkgName(msg.buffer);
@@ -270,6 +274,18 @@ void Service::processGetAppOwner(MessageBuffer &buffer, const Credentials &creds
         Serialization::Serialize(buffer, ownerUid);
 }
 
+void Service::processGetAppFullCreds(MessageBuffer &buffer, const Credentials &creds)
+{
+    uid_t puid, ownerUid;
+    std::string appName, pkgName;
+    Deserialization::Deserialize(buffer, puid);
+    int ret = m_serviceImpl.getAppFullCreds(puid, creds.pid, ownerUid, appName, pkgName);
+    buffer.ModeStreaming();
+    Serialization::Serialize(buffer, ret);
+    if (ret == SECURITY_MANAGER_SUCCESS)
+        Serialization::Serialize(buffer, ownerUid, appName, pkgName);
+}
+
 void Service::processGetPkgName(MessageBuffer &buffer)
 {
     std::string appName;