#include <sys/capability.h>
#include <sys/syscall.h>
#include <sys/mman.h>
+#include <sys/socket.h>
#include <signal.h>
#include <dpl/log/log.h>
return SECURITY_MANAGER_SUCCESS;
}
+static int pidToPuid(pid_t pid, uid_t &puid)
+{
+ struct stat st;
+ std::string path;
+ try {
+ path = "/proc/" + std::to_string(pid) + "/";
+ }
+ catch(const std::exception& e)
+ {
+ LogError("Path string allocation exception: " << e.what());
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ }
+
+ int ret = stat(path.c_str(), &st);
+ if (ret < 0) {
+ LogError("Access to " << path << " failed with : " << ret);
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ puid = st.st_uid;
+ return SECURITY_MANAGER_SUCCESS;
+}
+
SECURITY_MANAGER_API
int security_manager_prepare_app(const char *app_name)
{
SECURITY_MANAGER_API
int security_manager_identify_app_from_socket(int sockfd, char **pkg_name, char **app_name)
{
- return try_catch([&] {
- if(!smack_simple_check()) {
- LogWarning("Running in no-smack mode, returning static pkg_name default_app_no_Smack_mode & empty app_name");
- *pkg_name = strdup("default_app_no_Smack_mode");
- return *pkg_name ? (int)SECURITY_MANAGER_SUCCESS : (int)SECURITY_MANAGER_ERROR_MEMORY;
+ return try_catch([&]() -> int {
+ if(smack_simple_check()) {
+ return security_manager_identify_app([&] {
+ return SmackLabels::getSmackLabelFromSocket(sockfd);
+ }, pkg_name, app_name);
}
- return security_manager_identify_app([&] {
- return SmackLabels::getSmackLabelFromSocket(sockfd);
- }, pkg_name, app_name);
+
+ struct ucred credentials;
+ socklen_t length = sizeof(struct ucred);
+ int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &credentials, &length);
+ if (ret < 0) {
+ return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+ }
+
+ return security_manager_identify_app_from_pid(credentials.pid, pkg_name, app_name);
});
}
SECURITY_MANAGER_API
int security_manager_identify_app_from_pid(pid_t pid, char **pkg_name, char **app_name)
{
- return try_catch([&] {
- if(!smack_simple_check()) {
- LogWarning("Running in no-smack mode, returning static pkg_name default_app_no_Smack_mode & empty app_name");
- *pkg_name = strdup("default_app_no_Smack_mode");
- return *pkg_name ? (int)SECURITY_MANAGER_SUCCESS : (int)SECURITY_MANAGER_ERROR_MEMORY;
+ if (!pkg_name && !app_name)
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+ return try_catch([&]() -> int {
+ if(smack_simple_check()) {
+ return security_manager_identify_app([&] {
+ return SmackLabels::getSmackLabelFromPid(pid);
+ }, pkg_name, app_name);
}
- return security_manager_identify_app([&] {
- return SmackLabels::getSmackLabelFromPid(pid);
- }, pkg_name, app_name);
+
+ uid_t puid;
+ int ret = pidToPuid(pid, puid);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("Could not find a PUID for the given PID: " << pid);
+ return ret;
+ }
+
+ // Try to get the app name and package name using the PUID
+ std::string appNameString, pkgNameString;
+ return try_catch([&]() -> int {
+ ClientRequest request(SecurityModuleCall::APP_GET_NAME_AND_PKG);
+ request.send(puid);
+
+ if (!request.failed()) {
+ request.recv(appNameString, pkgNameString);
+ if (appNameString.empty() && pkgNameString.empty()) {
+ LogError("Empty return from APP_GET_NAME_AND_PKG from server!");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ LogInfo("Received app name: " << appNameString << " and pkg name: " <<
+ pkgNameString << " for PUID " << puid);
+
+ char *appName = nullptr;
+ if (app_name && !appNameString.empty() &&
+ !(appName = strdup(appNameString.c_str()))) {
+ LogError("Memory allocation in strdup failed.");
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ }
+
+ char *pkgName = nullptr;
+ if (pkg_name) {
+ if (!(pkgName = strdup(pkgNameString.c_str()))) {
+ free(appName);
+ LogError("Memory allocation in strdup failed.");
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ }
+ *pkg_name = pkgName;
+ }
+
+ if (app_name)
+ *app_name = appName;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ });
});
}
{
if (!app)
return SECURITY_MANAGER_ERROR_INPUT_PARAM;
- if (!smack_simple_check()) {
- LogWarning("Running in no-smack mode, can't (yet) determine if a process is an app or not");
- return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
- }
+
char * pkgId = NULL;
int ret = security_manager_identify_app_from_pid(pid, &pkgId, NULL);
return SECURITY_MANAGER_ERROR_INPUT_PARAM;
uid_t puid;
- struct stat st;
- std::string path;
- try {
- path = "/proc/" + std::to_string(pid) + "/";
- }
- catch(const std::exception& e)
- {
- LogError("Path string allocation exception: " << e.what());
- return SECURITY_MANAGER_ERROR_MEMORY;
- }
-
- int ret = stat(path.c_str(), &st);
- if (ret < 0) {
- LogError("Access to " << path << " failed with : " << ret);
- return SECURITY_MANAGER_ERROR_UNKNOWN;
+ int ret = pidToPuid(pid, puid);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("Could not find a PUID for the given PID: " << pid);
+ return ret;
}
- puid = st.st_uid;
if (smack_simple_check()) {
*uid = puid;
process_type type,
const char *app_id = nullptr)
{
- if (!smack_simple_check()) {
- LogWarning("Running in no-smack mode, exiting with success from security_manager_set_identity - not setting Smack");
- return SECURITY_MANAGER_SUCCESS;
- }
security_manager_pre_check();
+
+ if (smack_simple_check()) {
+ switch (type) {
+ case (process_type::SM_PROCESS_TYPE_SYSTEM):
+ if (smack_set_label_for_self(SMACK_SYSTEM.c_str()) != 0) {
+ LogError("Failed to set smack label" << SMACK_SYSTEM << "for current process");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ case (process_type::SM_PROCESS_TYPE_SYSTEM_PRIVILEGED):
+ if (smack_set_label_for_self(SMACK_SYSTEM_PRIVILEGED.c_str()) != 0) {
+ LogError("Failed to set smack label" << SMACK_SYSTEM_PRIVILEGED << "for current process");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ case (process_type::SM_PROCESS_TYPE_APP):
+ if (app_id == nullptr) {
+ LogError("app_id is NULL");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+ return security_manager_set_process_label_from_appid(app_id);
+ }
+
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ }
+
+ auto setSytemUid = [&]() -> int {
+ return try_catch([&]() -> int {
+ auto systemUid = getSystemUid();
+ if (setuid(systemUid)) {
+ LogError("Failed to set UID " << systemUid << " for current process");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ });
+ };
+
switch (type) {
case (process_type::SM_PROCESS_TYPE_SYSTEM):
- if (smack_set_label_for_self(SMACK_SYSTEM.c_str()) != 0) {
- LogError("Failed to set smack label" << SMACK_SYSTEM << "for current process");
- return SECURITY_MANAGER_ERROR_UNKNOWN;
- }
- return SECURITY_MANAGER_SUCCESS;
case (process_type::SM_PROCESS_TYPE_SYSTEM_PRIVILEGED):
- if (smack_set_label_for_self(SMACK_SYSTEM_PRIVILEGED.c_str()) != 0) {
- LogError("Failed to set smack label" << SMACK_SYSTEM_PRIVILEGED << "for current process");
- return SECURITY_MANAGER_ERROR_UNKNOWN;
- }
- return SECURITY_MANAGER_SUCCESS;
+ return setSytemUid();
case (process_type::SM_PROCESS_TYPE_APP):
if (app_id == nullptr) {
LogError("app_id is NULL");
return SECURITY_MANAGER_ERROR_INPUT_PARAM;
}
- return security_manager_set_process_label_from_appid(app_id);
- }
+ std::string puidString, agidString;
+ uid_t puid = 0;
+ gid_t agid = 0;
+
+ int ret = try_catch([&]() -> int {
+ ClientRequest request(SecurityModuleCall::APP_GET_PUID_AND_AGID);
+ request.send(std::string(app_id));
+ if (!request.failed()) {
+ request.recv(puidString, agidString);
+ if (puidString.empty()) {
+ LogError("Empty return from APP_GET_PUID_AND_AGID from server!");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ LogInfo("Received PUID: " << puidString << " and AGID: " << agidString << " for app_id " << app_id);
+ puid = std::stoi(puidString);
+ if (!agidString.empty())
+ agid = std::stoi(agidString);
+ }
+ return request.getStatus();
+ });
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("Failed request for app PUID and AGID");
+ return ret;
+ }
+
+ if (setuid(puid)) {
+ LogError("Failed to set UID " << puid << "for current process");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+
+ if (agidString.empty())
+ return SECURITY_MANAGER_SUCCESS;
+
+ gid_t groups[] = { agid };
+ if (setgroups(1, groups)) {
+ LogError("Failed to set supplementary group " << agid << "for current process");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ }
return SECURITY_MANAGER_SUCCESS;
}
ERemoveApplication,
EPkgNameExists,
EAppNameExists,
+ EGetAppNameAndPkg,
EGetAppOwner,
EGetAppPkgName,
EGetAppPkgInfo,
+ EGetAppPuidAndAgid,
EGetAppVersion,
EGetPathSharedCount,
EGetTargetPathSharedCount,
*/
bool AuthorExists(const std::string &authorHash);
+ /**
+ * Return the name and package name of an application given its puid
+ *
+ * @param puid - the puid identifying the application
+ * @param[out] appName - return application's name
+ * @param[out] pkgName - return application's package name
+ * @exception PrivilegeDb::Exception::InternalError on internal error
+ * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+ */
+ void GetAppNameAndPkg(uid_t puid, std::string &appName, std::string &pkgName);
+
/**
* Return the uid of and application's owner given its puid
*
*/
bool GetAppPkgInfo(const std::string &appName, std::string &pkgName, bool &isHybrid, bool &isSharedRO);
+ /**
+ * Return application puid and agid associated with a given application id
+ *
+ * @param appName - application identifier
+ * @param[out] puid - return application's process id (PUID)
+ * @param[out] guid - return application's author id (AGID)
+ * @exception PrivilegeDb::Exception::InternalError on internal error
+ * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+ */
+ void GetAppPuidAndAgid(const std::string &appName, std::string &puid, std::string &agid);
+
/**
* Return Tizen version associated with a given application identifier
*
APP_INSTALL,
APP_UPDATE,
APP_UNINSTALL,
+ APP_GET_NAME_AND_PKG,
APP_GET_OWNER,
APP_GET_PKG_NAME,
+ APP_GET_PUID_AND_AGID,
APP_APPLY_PRIVATE_SHARING,
APP_DROP_PRIVATE_SHARING,
USER_ADD,
*/
int appUninstall(const Credentials &creds, app_inst_req &req);
+ /**
+ * Process a request to get an application's name and pkg name.
+ * Retrieves the name and package name of an application's given its puid.
+ *
+ * @param[in] puid application process identifier
+ * @param[out] appName returned application name
+ * @param[out] pkgName returned package name
+ *
+ * @return API return code, as defined in protocols.h
+ */
+ int getAppNameAndPkg(uid_t puid, std::string &appName, std::string &pkgName);
+
/**
* Process a request to get an application's owner uid.
* Retrieves the uid of and application's owner given its puid.
*/
int getPkgName(const std::string &appName, std::string &pkgName);
+ /**
+ * Process app puid and agid query.
+ * Retrieves the app puid and agid associated with given application id.
+ *
+ * @param[in] appName application identifier
+ * @param[out] puid returned application's process id (PUID)
+ * @param[out] agid returned application's author id (AGID)
+ *
+ * @return API return code, as defined in protocols.h
+ */
+ int getPuidAndAgid(const std::string &appName, std::string &puid, std::string &agid);
+
/**
* Process user adding request.
*
gid_t getGidByName(const std::string& name);
[[maybe_unused]] gid_t getSystemAccessGid();
+
+[[maybe_unused]] uid_t getUidByName(const std::string& name);
+[[maybe_unused]] uid_t getSystemUid();
} /* namespace SecurityManager */
template <class...T>
[underlying(StmtType::ERemoveApplication)] = "DELETE FROM user_app_pkg_view WHERE app_name=? AND uid=?",
[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 = ?",
[underlying(StmtType::EGetAppVersion)] = "SELECT version FROM app WHERE name = ?",
[underlying(StmtType::EGetPathSharedCount)] = "SELECT COUNT(*) FROM app_private_sharing_view WHERE path = ?",
[underlying(StmtType::EGetTargetPathSharedCount)] = "SELECT COUNT(*) FROM app_private_sharing_view WHERE target_app_name = ? AND path = ?",
});
}
+void PrivilegeDb::GetAppNameAndPkg(uid_t puid, std::string &appName, std::string &pkgName)
+{
+ return try_catch_db(m_api_mutex, [&] {
+ appName.clear();
+ pkgName.clear();
+
+ auto command = getStatement(StmtType::EGetAppNameAndPkg);
+ command->BindInteger(1, puid);
+ command->BindInteger(2, puid);
+
+ int isHybrid;
+ std::string firstAppName;
+ if (command->Step()) {
+ isHybrid = command->GetColumnInteger(0);
+ firstAppName = command->GetColumnString(1);
+ pkgName = command->GetColumnString(2);
+ }
+ else {
+ LogError("Could not find an app name and pkg name for the PUID given: " << puid);
+ return;
+ }
+
+ // It is only possible to determine the app name in case of hybrid apps
+ // or when there is only one row (package with only one app)
+ if (isHybrid || !command->Step())
+ appName = firstAppName;
+ });
+}
+
bool PrivilegeDb::GetAppOwner(uid_t puid, uid_t &ownerId)
{
return try_catch_db(m_api_mutex, [&] {
});
}
+void PrivilegeDb::GetAppPuidAndAgid(const std::string &appName, std::string &puid, std::string &agid)
+{
+ return try_catch_db(m_api_mutex, [&] {
+ puid.clear();
+ agid.clear();
+
+ auto command = getStatement(StmtType::EGetAppPuidAndAgid);
+ command->BindString(1, appName);
+
+ if (command->Step()) {
+ puid = command->GetColumnString(0);
+ agid = command->GetColumnString(1);
+ }
+ else {
+ LogError("Could not find a PUID and AGID for the app id given: " << appName);
+ return;
+ }
+ });
+}
+
void PrivilegeDb::GetAppVersion(const std::string &appName, std::string &tizenVer)
{
return try_catch_db(m_api_mutex, [&] {
SM_CODE_DESCRIBE(SecurityModuleCall::APP_INSTALL);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_UPDATE);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_UNINSTALL);
+ SM_CODE_DESCRIBE(SecurityModuleCall::APP_GET_NAME_AND_PKG);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_GET_OWNER);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_GET_PKG_NAME);
+ SM_CODE_DESCRIBE(SecurityModuleCall::APP_GET_PUID_AND_AGID);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_APPLY_PRIVATE_SHARING);
SM_CODE_DESCRIBE(SecurityModuleCall::APP_DROP_PRIVATE_SHARING);
SM_CODE_DESCRIBE(SecurityModuleCall::USER_ADD);
return SECURITY_MANAGER_SUCCESS;
}
+int ServiceImpl::getAppNameAndPkg(uid_t puid, std::string &appName, std::string &pkgName)
+{
+ try {
+ m_privilegeDb.GetAppNameAndPkg(puid, appName, pkgName);
+ if (pkgName.empty()) {
+ return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+ } else {
+ LogDebug("appName: " << appName << ", pkgName: " << pkgName);
+ }
+ } catch (const PrivilegeDb::Exception::Base &e) {
+ LogError("Error while getting appName and pkgName from database: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ }
+
+ return SECURITY_MANAGER_SUCCESS;
+}
+
int ServiceImpl::getAppOwner(uid_t puid, uid_t &ownerId)
{
try {
return SECURITY_MANAGER_SUCCESS;
}
+int ServiceImpl::getPuidAndAgid(const std::string &appName, std::string &puid, std::string &agid)
+{
+ LogDebug("appName: " << appName);
+
+ try {
+ m_privilegeDb.GetAppPuidAndAgid(appName, puid, agid);
+ if (puid.empty()) {
+ LogWarning("Application " << appName << " not found in database");
+ return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+ } else {
+ LogDebug("puid: " << puid << ", agid: " << agid);
+ }
+ } catch (const PrivilegeDb::Exception::Base &e) {
+ LogError("Error while getting app puid and agid from database: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ }
+
+ return SECURITY_MANAGER_SUCCESS;
+}
+
int ServiceImpl::userAdd(const Credentials &creds, uid_t uidAdded, int userType)
{
if (!authenticate(creds, PRIVILEGE_USER_ADMIN)) {
#include <fcntl.h>
#include <functional>
#include <grp.h>
+#include <pwd.h>
#include <system_error>
#include <utils.h>
return gid;
}
+uid_t getUidByName(const std::string& name) {
+ struct passwd pwd;
+ struct passwd *res = nullptr;
+ char buf[1024];
+ if (0 != getpwnam_r(name.c_str(), &pwd, buf, sizeof(buf), &res) || res == nullptr) {
+ LogErrno("getpwnam_r()");
+ throw std::runtime_error("getpwnam_r() failed");
+ }
+
+ return pwd.pw_uid;
+}
+
+uid_t getSystemUid() {
+ const static uid_t uid = getGidByName("system");
+ return uid;
+}
+
} /* namespace SecurityManager */
*/
void processAppUninstall(MessageBuffer &buffer, const Credentials &creds);
+ /**
+ * Process getting app name and package name from an app puid
+ *
+ * @param buffer Input/output message buffer
+ */
+ void processGetAppNameAndPkg(MessageBuffer &buffer);
+
/**
* Process getting owner uid identifier from an app puid
*
*/
void processGetPkgName(MessageBuffer &buffer);
+ /**
+ * Process getting the PUID and AGID from an app identifier
+ *
+ * @param buffer Input/output message buffer
+ */
+ void processGetPuidAndAgid(MessageBuffer &buffer);
+
void processUserAdd(MessageBuffer &buffer, const Credentials &creds);
void processUserDelete(MessageBuffer &buffer, const Credentials &creds);
LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
processAppUninstall(msg.buffer, msg.creds);
break;
+ case SecurityModuleCall::APP_GET_NAME_AND_PKG:
+ LogDebug("call_type: SecurityModuleCall::APP_GET_NAME_AND_PKG");
+ processGetAppNameAndPkg(msg.buffer);
+ break;
case SecurityModuleCall::APP_GET_OWNER:
LogDebug("call_type: SecurityModuleCall::APP_GET_OWNER");
processGetAppOwner(msg.buffer);
LogDebug("call_type: SecurityModuleCall::APP_GET_PKG_NAME");
processGetPkgName(msg.buffer);
break;
+ case SecurityModuleCall::APP_GET_PUID_AND_AGID:
+ LogDebug("call_type: SecurityModuleCall::APP_GET_PUID_AND_AGID");
+ processGetPuidAndAgid(msg.buffer);
+ break;
case SecurityModuleCall::USER_ADD:
LogDebug("call_type: SecurityModuleCall::USER_ADD");
processUserAdd(msg.buffer, msg.creds);
Serialization::Serialize(buffer, m_serviceImpl.appUninstall(creds, req));
}
+void Service::processGetAppNameAndPkg(MessageBuffer &buffer)
+{
+ uid_t puid;
+ std::string appName, pkgName;
+
+ Deserialization::Deserialize(buffer, puid);
+ int ret = m_serviceImpl.getAppNameAndPkg(puid, appName, pkgName);
+ buffer.ModeStreaming();
+ Serialization::Serialize(buffer, ret);
+ if (ret == SECURITY_MANAGER_SUCCESS)
+ Serialization::Serialize(buffer, appName, pkgName);
+}
+
void Service::processGetAppOwner(MessageBuffer &buffer)
{
uid_t puid;
Serialization::Serialize(buffer, pkgName);
}
+void Service::processGetPuidAndAgid(MessageBuffer &buffer)
+{
+ std::string appName;
+ std::string puid, agid;
+ int ret;
+
+ Deserialization::Deserialize(buffer, appName);
+ ret = m_serviceImpl.getPuidAndAgid(appName, puid, agid);
+ buffer.ModeStreaming();
+ Serialization::Serialize(buffer, ret);
+ if (ret == SECURITY_MANAGER_SUCCESS)
+ Serialization::Serialize(buffer, puid, agid);
+}
+
void Service::processUserAdd(MessageBuffer &buffer, const Credentials &creds)
{
int ret;