using namespace SecurityManager;
return try_catch([&]() -> int {
ClientRequest request(SecurityModuleCall::APP_GET_OWNER);
- request.send(puid);
+ request.send();
if (!request.failed()) {
request.recv(ownerId);
LogInfo("Received ownerId: " << ownerId << " for app PID " << pid);
${COMMON_PATH}/protocols.cpp
${COMMON_PATH}/nsmount-logic.cpp
${COMMON_PATH}/path-setup.cpp
+ ${COMMON_PATH}/pid-to-owner.cpp
${COMMON_PATH}/privilege_db.cpp
${COMMON_PATH}/smack-labels.cpp
${COMMON_PATH}/smack-accesses.cpp
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <optional>
+#include <unordered_map>
+
+#include <sys/types.h>
+
+namespace SecurityManager {
+
+class PidToOwner {
+public:
+ void add(pid_t pid, uid_t owner);
+ void remove(pid_t pid);
+ std::optional<uid_t> get(pid_t pid) const;
+
+private:
+ std::unordered_map<pid_t, uid_t> m_pid2Owner;
+ mutable std::mutex m_apiMutex;
+};
+
+} // namespace SecurityManager
EPkgNameExists,
EAppNameExists,
EGetAppNameAndPkg,
- EGetAppOwner,
EGetAppPkgName,
EGetAppPkgInfo,
EGetAppPuidAndAgid,
*/
void GetAppNameAndPkg(uid_t puid, std::string &appName, std::string &pkgName);
- /**
- * Return the uid of and application's owner given its puid
- *
- * @param puid - the puid identifying the application
- * @param[out] ownerId - return application's owner's id
- * @exception PrivilegeDb::Exception::InternalError on internal error
- * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
- * @return true if owner is found in the database
- */
- bool GetAppOwner(uid_t puid, uid_t &ownerId);
-
/**
* Return package id associated with a given application id
*
#include "security-manager.h"
#include "smack-common.h"
#include "smack-rules.h"
+#include "pid-to-owner.h"
#include "protocols.h"
#include "privilege_db.h"
#include "privilege-gids.h"
* Process a request to get an application's owner uid.
* Retrieves the uid of and application's owner given its puid.
*
- * @param[in] puid application process identifier
+ * @param[in] pid application process identifier
* @param[out] ownerId returned application owner uid
*
* @return API return code, as defined in protocols.h
*/
- int getAppOwner(uid_t puid, uid_t &ownerId);
+ int getAppOwner(pid_t pid, uid_t &ownerId);
/**
* Process package id query.
SmackRules m_smackRules; // seems to work out of the box, assuming that libsmack can be used from many threads at once
PrivilegeDb m_privilegeDb; // added api mutex -> if one thread only does RW ScopedTransactions (from service_impl), its okay
CynaraAdmin m_cynaraAdmin; // added api mutex
+ PidToOwner m_pidToOwner; // added api mutex
PrivilegeGids m_privilegeGids; // seems to work out of the box, all accessed methods are const
NSMountLogic m_NSMountLogic;// is okay, used only on policy update
// below elements are set once and not changed, can be read from many threads
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pid-to-owner.h"
+
+#include "smack-check.h"
+
+namespace SecurityManager {
+
+void PidToOwner::add(pid_t pid, uid_t owner)
+{
+ if (smack_simple_check())
+ return;
+
+ std::lock_guard guard(m_apiMutex);
+ m_pid2Owner[pid] = owner;
+}
+
+void PidToOwner::remove(pid_t pid)
+{
+ if (smack_simple_check())
+ return;
+
+ std::lock_guard guard(m_apiMutex);
+ m_pid2Owner.erase(pid);
+}
+
+std::optional<uid_t> PidToOwner::get(pid_t pid) const
+{
+ if (smack_simple_check())
+ return std::nullopt;
+
+ std::lock_guard guard(m_apiMutex);
+
+ auto it = m_pid2Owner.find(pid);
+ if (it == m_pid2Owner.end())
+ return std::nullopt;
+
+ return it->second;
+}
+
+} // namespace SecurityManager
[underlying(StmtType::EPkgNameExists)] = "SELECT count(*) FROM pkg WHERE name=?",
[underlying(StmtType::EAppNameExists)] = "SELECT count(*) FROM app WHERE name=?",
[underlying(StmtType::EGetAppNameAndPkg)] = "SELECT is_hybrid, app_name, pkg_name FROM user_app_pkg_view WHERE (is_hybrid = 1 AND app_id = ?) OR (is_hybrid = 0 AND pkg_id = ?)",
- [underlying(StmtType::EGetAppOwner)] = "SELECT uid, sum(is_hybrid) FROM user_app_pkg_view WHERE (is_hybrid = 1 AND app_id = ?) OR (is_hybrid = 0 AND pkg_id = ?) GROUP BY uid",
[underlying(StmtType::EGetAppPkgName)] = "SELECT pkg_name FROM user_app_pkg_view WHERE app_name = ?",
[underlying(StmtType::EGetAppPkgInfo)] = "SELECT pkg.name, pkg.is_hybrid, pkg.shared_ro FROM app, pkg WHERE app.name = ? AND app.pkg_id = pkg.pkg_id",
[underlying(StmtType::EGetAppPuidAndAgid)] = "SELECT CASE WHEN (is_hybrid = 1) THEN app_id ELSE pkg_id END, author_id FROM user_app_pkg_view WHERE app_name = ?",
});
}
-bool PrivilegeDb::GetAppOwner(uid_t puid, uid_t &ownerId)
-{
- return try_catch_db(m_api_mutex, [&] {
- auto command = getStatement(StmtType::EGetAppOwner);
- command->BindInteger(1, puid);
- command->BindInteger(2, puid);
-
- if (command->Step())
- ownerId = command->GetColumnInteger(0);
- else {
- LogError("Could not find an owner UID for the PUID given: " << puid);
- return false;
- }
-
- // Check how many hybrid apps with the same owner UID and PUID there are.
- // In case there is more than 1, an error must have occured.
- int hybridSum = command->GetColumnInteger(1);
- if (hybridSum > 1)
- ThrowMsg(PrivilegeDb::Exception::InternalError,
- "More than 1 hybrid app with given PUID found");
-
- // Check the next rows.
- // There should not be any more entries with the same PUID but a diferent owner UID.
- if (command->Step())
- ThrowMsg(PrivilegeDb::Exception::InternalError,
- "More than 1 owner UID found for the app with given PUID");
-
- return true;
- });
-}
-
void PrivilegeDb::GetAppPkgName(const std::string &appName, std::string &pkgName)
{
return try_catch_db(m_api_mutex, [&] {
return SECURITY_MANAGER_SUCCESS;
}
-int ServiceImpl::getAppOwner(uid_t puid, uid_t &ownerId)
+int ServiceImpl::getAppOwner(pid_t pid, uid_t &ownerId)
{
- try {
- if (!m_privilegeDb.GetAppOwner(puid, ownerId)) {
- LogWarning("Application with uid: " << puid << " not found in database");
- return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
- } else {
- LogDebug("ownerId: " << ownerId);
- }
- } catch (const PrivilegeDb::Exception::Base &e) {
- LogError("Error while getting ownerId from database: " << e.DumpToString());
- return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ auto uid = m_pidToOwner.get(pid);
+ if (!uid) {
+ LogWarning("No app for pid " << pid << " found in owner mapping");
+ return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+ } else {
+ ownerId = *uid;
+ LogInfo("ownerId: " << ownerId);
}
return SECURITY_MANAGER_SUCCESS;
if (pids.empty())
ret = FS::removeDirectory(appDir);
+ m_pidToOwner.remove(pid);
return ret;
}
ret = getForbiddenAndAllowedGroups(allowedPrivileges, forbiddenGroups, allowedGroups);
-
LogWarning("getForbiddenAndAllowedGroups returned: " << ret);
- return ret != SECURITY_MANAGER_SUCCESS ? ret
- : appSetupNamespace(creds, id.uid, id.label, privPathsVector, privPathsStatusVector);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+ ret = appSetupNamespace(creds, id.uid, id.label, privPathsVector, privPathsStatusVector);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+ m_pidToOwner.add(creds.pid, creds.uid);
+ return SECURITY_MANAGER_SUCCESS;
} catch (const FS::Exception::Base &e) {
LogError("Filesystem error: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
int security_manager_is_app_from_pid(pid_t pid, bool *app);
/**
- * Return the UID of the user for which the app was installed.
+ * Return the UID of the user on behalf of which the app has been started.
* Only in No-Smack mode does this function check if the PID is an actual app.
*
* \param[out] uid the user ID of application user
* Process getting owner uid identifier from an app puid
*
* @param buffer Input/output message buffer
+ * @param creds credentials of the requesting process
*/
- void processGetAppOwner(MessageBuffer &buffer);
+ void processGetAppOwner(MessageBuffer &buffer, const Credentials &creds);
/**
* Process getting package identifier from an app identifier
break;
case SecurityModuleCall::APP_GET_OWNER:
LogDebug("call_type: SecurityModuleCall::APP_GET_OWNER");
- processGetAppOwner(msg.buffer);
+ processGetAppOwner(msg.buffer, msg.creds);
break;
case SecurityModuleCall::APP_GET_PKG_NAME:
LogDebug("call_type: SecurityModuleCall::APP_GET_PKG_NAME");
Serialization::Serialize(buffer, appName, pkgName);
}
-void Service::processGetAppOwner(MessageBuffer &buffer)
+void Service::processGetAppOwner(MessageBuffer &buffer, const Credentials &creds)
{
- uid_t puid;
uid_t ownerUid;
- Deserialization::Deserialize(buffer, puid);
- int ret = m_serviceImpl.getAppOwner(puid, ownerUid);
+ int ret = m_serviceImpl.getAppOwner(creds.pid, ownerUid);
buffer.ModeStreaming();
Serialization::Serialize(buffer, ret);
if (ret == SECURITY_MANAGER_SUCCESS)