* @brief Implementation of SocketManager.
*/
-#include <set>
-
#include <errno.h>
#include <fcntl.h>
#include <linux/xattr.h>
}
SocketManager::SocketDescription&
-SocketManager::CreateDefaultReadSocketDescription(int sock, bool timeout)
+SocketManager::CreateDefaultReadSocketDescription(int sock)
{
if ((int)m_socketDescriptionVector.size() <= sock)
m_socketDescriptionVector.resize(sock+20);
auto &desc = m_socketDescriptionVector[sock];
- desc.isListen = false;
desc.isOpen = true;
- desc.interfaceID = 0;
- desc.service = NULL;
+ desc.timeout = monotonicNow() + SOCKET_TIMEOUT;
desc.counter = ++m_counter;
- if (timeout) {
- desc.timeout = monotonicNow() + SOCKET_TIMEOUT;
- if (false == desc.isTimeout) {
- Timeout tm;
- tm.time = desc.timeout;
- tm.sock = sock;
- m_timeoutQueue.push(tm);
- }
+ if (false == desc.isTimeout) {
+ desc.isTimeout = true;
+ Timeout tm;
+ tm.time = desc.timeout;
+ tm.sock = sock;
+ m_timeoutQueue.push(tm);
}
- desc.isTimeout = timeout;
-
RegisterFdForReading(sock);
return desc;
}
}
SocketManager::~SocketManager() {
- std::set<GenericSocketService*> serviceMap;
-
- // Find all services. Set is used to remove duplicates.
- // In this implementation, services are not able to react in any way.
- for (size_t i=0; i < m_socketDescriptionVector.size(); ++i)
- if (m_socketDescriptionVector[i].isOpen)
- serviceMap.insert(m_socketDescriptionVector[i].service);
-
- // Time to destroy all services.
- for (auto it = serviceMap.begin(); it != serviceMap.end(); ++it) {
- LogDebug("delete " << (void*)(*it));
- (*it)->Stop();
- delete *it;
+ if (m_service) {
+ m_service->Stop();
+ delete m_service;
}
for (size_t i = 0; i < m_socketDescriptionVector.size(); ++i)
// All service sockets have been closed. Close internal descriptors.
close(m_signalFd);
+ close(m_listenSock);
close(m_notifyMe);
}
-void SocketManager::ReadyForAccept(int sock) {
+void SocketManager::ReadyForAccept() {
struct sockaddr_un clientAddr;
unsigned int clientLen = sizeof(clientAddr);
- int client = accept4(sock, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK);
+ int client = accept4(m_listenSock, (struct sockaddr*) &clientAddr, &clientLen, SOCK_NONBLOCK);
// LogInfo("Accept on sock: " << sock << " Socket opended: " << client);
if (-1 == client) {
int err = errno;
return;
}
- auto &desc = CreateDefaultReadSocketDescription(client, true);
- desc.interfaceID = m_socketDescriptionVector[sock].interfaceID;
- desc.service = m_socketDescriptionVector[sock].service;
+ auto &desc = CreateDefaultReadSocketDescription(client);
GenericSocketService::AcceptEvent event(
ConnectionID{client, desc.counter},
- desc.interfaceID,
Credentials::getCredentialsFromSocket(client));
- desc.service->Event(std::move(event));
+ m_service->Event(std::move(event));
}
// true if quit mainloop
}
void SocketManager::ReadyForRead(int sock) {
- if (m_socketDescriptionVector[sock].isListen) {
- ReadyForAccept(sock);
- return;
- }
-
GenericSocketService::ReadEvent event;
event.connectionID.sock = sock;
event.connectionID.counter = m_socketDescriptionVector[sock].counter;
CloseSocket(sock);
} else if (size >= 0) {
event.rawBuffer.resize(size);
- desc.service->Event(std::move(event));
+ m_service->Event(std::move(event));
} else if (size == -1) {
int err = errno;
switch (err) {
event.size = result;
event.left = desc.rawBuffer.size();
- desc.service->Event(std::move(event));
+ m_service->Event(std::move(event));
}
void SocketManager::MainLoop() {
return;
FD_CLR(m_signalFd, &readSet);
}
+ if (FD_ISSET(m_listenSock, &readSet)) {
+ ReadyForAccept();
+ FD_CLR(m_listenSock, &readSet);
+ }
if (FD_ISSET(m_notifyMe, &readSet)) {
eventfd_t dummyValue;
TEMP_FAILURE_RETRY(eventfd_read(m_notifyMe, &dummyValue));
{
int fd;
- // TODO optimalization - do it once in object constructor
- // and remember all information path->sockfd
+ // TODO optimization - do it once in object constructor
+ // and remember all information path->sockfd
int n = sd_listen_fds(0);
LogInfo("sd_listen_fds returns: " << n);
}
void SocketManager::CreateDomainSocket(
- GenericSocketService *service,
const GenericSocketService::ServiceDescription &desc)
{
int sockfd = GetSocketFromSystemD(desc);
- if (-1 == sockfd) {
- if (desc.systemdOnly) {
- LogError("Socket " << desc.serviceHandlerPath << " not provided by systemd.");
- ThrowMsg(Exception::InitFailed, "Socket " << desc.serviceHandlerPath <<
- " must be provided by systemd, but it was not.");
- }
+ if (-1 == sockfd)
sockfd = CreateDomainSocketHelp(desc);
- }
- auto &description = CreateDefaultReadSocketDescription(sockfd, false);
-
- description.isListen = true;
- description.interfaceID = desc.interfaceID;
- description.service = service;
+ m_listenSock = sockfd;
+ RegisterFdForReading(sockfd);
LogDebug("Listen on socket: " << sockfd <<
" Handler: " << desc.serviceHandlerPath.c_str());
void SocketManager::RegisterSocketService(GenericSocketService *service) {
service->SetSocketManager(this);
- auto serviceVector = service->GetServiceDescription();
- Try {
- for (auto iter = serviceVector.begin(); iter != serviceVector.end(); ++iter)
- CreateDomainSocket(service, *iter);
- } Catch(Exception::Base) {
- for (int i =0; i < (int)m_socketDescriptionVector.size(); ++i)
- {
- auto &desc = m_socketDescriptionVector[i];
- if (desc.service == service && desc.isOpen) {
- close(i);
- desc.isOpen = false;
- }
- }
- ReThrow(Exception::Base);
- }
+ CreateDomainSocket(service->GetServiceDescription());
+ m_service = service;
}
void SocketManager::Close(ConnectionID connectionID) {
GenericSocketService::CloseEvent event;
event.connectionID.sock = sock;
event.connectionID.counter = desc.counter;
- auto service = desc.service;
desc.isOpen = false;
- desc.service = NULL;
- desc.interfaceID = -1;
desc.rawBuffer.clear();
- if (service)
- service->Event(std::move(event));
- else
- LogError("Critical! Service is NULL! This should never happend!");
-
close(sock);
FD_CLR(sock, &m_readSet);
FD_CLR(sock, &m_writeSet);
/*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 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.
namespace SecurityManager {
-const InterfaceID IFACE = 1;
-
Service::Service(Offline offline) : BaseService(offline) {}
-GenericSocketService::ServiceDescriptionVector Service::GetServiceDescription()
+static const GenericSocketService::ServiceDescription serviceDesc{
+ SERVICE_SOCKET, /* path */
+ "*" /* smackLabel label (not used, we rely on systemd) */
+};
+
+const GenericSocketService::ServiceDescription &Service::GetServiceDescription() const
{
- return ServiceDescriptionVector {
- {SERVICE_SOCKET, /* path */
- "*", /* smackLabel label (not used, we rely on systemd) */
- IFACE, /* InterfaceID */
- false}, /* systemdOnly */
- };
+ return serviceDesc;
}
-bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
- InterfaceID interfaceID)
+bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer)
{
- LogDebug("Iteration begin. Interface = " << interfaceID);
+ LogDebug("Iteration begin.");
//waiting for all data
if (!buffer.Ready()) {
}
MessageBuffer send;
- bool retval = false;
-
- if (IFACE == interfaceID) {
- Try {
- Credentials &creds = m_connectionInfoMap.at(conn.counter).creds;
- // deserialize API call type
- int call_type_int;
- Deserialization::Deserialize(buffer, call_type_int);
- SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
- LOG_EXECUTION_TIME(SecurityModuleCallToString(call_type), creds);
- switch (call_type) {
- case SecurityModuleCall::NOOP:
- LogDebug("call_type: SecurityModuleCall::NOOP");
- Serialization::Serialize(send, static_cast<int>(SECURITY_MANAGER_SUCCESS));
- break;
- case SecurityModuleCall::APP_INSTALL:
- LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
- processAppInstall(buffer, send, creds);
- break;
- case SecurityModuleCall::APP_UPDATE:
- LogDebug("call_type: SecurityModuleCall::APP_UPDATE");
- processAppUpdate(buffer, send, creds);
- break;
- case SecurityModuleCall::APP_UNINSTALL:
- LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
- processAppUninstall(buffer, send, creds);
- break;
- case SecurityModuleCall::APP_GET_PKG_NAME:
- LogDebug("call_type: SecurityModuleCall::APP_GET_PKG_NAME");
- processGetPkgName(buffer, send);
- break;
- case SecurityModuleCall::USER_ADD:
- LogDebug("call_type: SecurityModuleCall::USER_ADD");
- processUserAdd(buffer, send, creds);
- break;
- case SecurityModuleCall::USER_DELETE:
- LogDebug("call_type: SecurityModuleCall::USER_DELETE");
- processUserDelete(buffer, send, creds);
- break;
- case SecurityModuleCall::POLICY_UPDATE:
- LogDebug("call_type: SecurityModuleCall::POLICY_UPDATE");
- processPolicyUpdate(buffer, send, creds);
- break;
- case SecurityModuleCall::GET_CONF_POLICY_ADMIN:
- LogDebug("call_type: SecurityModuleCall::GET_CONF_POLICY_ADMIN");
- processGetConfiguredPolicy(buffer, send, creds, true);
- break;
- case SecurityModuleCall::GET_CONF_POLICY_SELF:
- LogDebug("call_type: SecurityModuleCall::GET_CONF_POLICY_SELF");
- processGetConfiguredPolicy(buffer, send, creds, false);
- break;
- case SecurityModuleCall::GET_POLICY:
- LogDebug("call_type: SecurityModuleCall::GET_POLICY");
- processGetPolicy(buffer, send, creds);
- break;
- case SecurityModuleCall::POLICY_GET_DESCRIPTIONS:
- LogDebug("call_type: SecurityModuleCall::POLICY_GET_DESCRIPTIONS");
- processPolicyGetDesc(send);
- break;
- case SecurityModuleCall::GROUPS_GET:
- LogDebug("call_type: SecurityModuleCall::GROUPS_GET");
- processGetForbiddenAndAllowedGroups(buffer, send, creds);
- break;
- case SecurityModuleCall::GROUPS_FOR_UID:
- processGroupsForUid(buffer, send);
- break;
- case SecurityModuleCall::APP_HAS_PRIVILEGE:
- LogDebug("call_type: SecurityModuleCall::APP_HAS_PRIVILEGE");
- processAppHasPrivilege(buffer, send, creds);
- break;
- case SecurityModuleCall::APP_APPLY_PRIVATE_SHARING:
- LogDebug("call_type: SecurityModuleCall::APP_APPLY_PRIVATE_SHARING");
- processApplyPrivateSharing(buffer, send, creds);
- break;
- case SecurityModuleCall::APP_DROP_PRIVATE_SHARING:
- LogDebug("call_type: SecurityModuleCall::APP_DROP_PRIVATE_SHARING");
- processDropPrivateSharing(buffer, send, creds);
- break;
- case SecurityModuleCall::PATHS_REGISTER:
- processPathsRegister(buffer, send, creds);
- break;
- case SecurityModuleCall::SHM_APP_NAME:
- processShmAppName(buffer, send, creds);
- break;
- case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER:
- LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER");
- processGetAppDefinedPrivilegeProvider(buffer, send);
- break;
- case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE:
- LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE");
- processGetAppDefinedPrivilegeLicense(buffer, send);
- break;
- case SecurityModuleCall::GET_CLIENT_PRIVILEGE_LICENSE:
- LogDebug("call_type: SecurityModuleCall::GET_CLIENT_PRIVILEGE_PROVIDER");
- processGetClientPrivilegeLicense(buffer, send);
- break;
- case SecurityModuleCall::APP_CLEAN_NAMESPACE:
- LogDebug("call_type: SecurityModuleCall::APP_CLEAN_NAMESPACE");
- processAppCleanNamespace(buffer, send, creds);
- break;
- case SecurityModuleCall::GET_APP_MANIFEST_POLICY:
- LogDebug("call_type: SecurityModuleCall::GET_APP_MANIFEST_POLICY");
- processAppGetManifestPolicy(buffer, send, creds);
- break;
- case SecurityModuleCall::GET_PROCESS_LABEL:
- processGetProcessLabel(buffer, send);
- break;
- case SecurityModuleCall::PREPARE_APP:
- prepareApp(buffer, send, creds);
- break;
- default:
- LogError("Invalid call: " << call_type_int);
- Throw(ServiceException::InvalidAction);
- }
- // if we reach this point, the protocol is OK
- retval = true;
- } Catch(MessageBuffer::Exception::Base) {
- LogError("Broken protocol.");
- } Catch(ServiceException::Base) {
- LogError("Broken protocol.");
- } catch (const std::exception &e) {
- LogError("STD exception " << e.what());
- } catch (...) {
- LogError("Unknown exception");
- }
- } else {
- LogError("Wrong interface");
- }
- if (retval) {
- //send response
+ Try {
+ Credentials &creds = m_connectionInfoMap.at(conn.counter).creds;
+ // deserialize API call type
+ int call_type_int;
+ Deserialization::Deserialize(buffer, call_type_int);
+ SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
+ LOG_EXECUTION_TIME(SecurityModuleCallToString(call_type), creds);
+ switch (call_type) {
+ case SecurityModuleCall::NOOP:
+ LogDebug("call_type: SecurityModuleCall::NOOP");
+ Serialization::Serialize(send, static_cast<int>(SECURITY_MANAGER_SUCCESS));
+ break;
+ case SecurityModuleCall::APP_INSTALL:
+ LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
+ processAppInstall(buffer, send, creds);
+ break;
+ case SecurityModuleCall::APP_UPDATE:
+ LogDebug("call_type: SecurityModuleCall::APP_UPDATE");
+ processAppUpdate(buffer, send, creds);
+ break;
+ case SecurityModuleCall::APP_UNINSTALL:
+ LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
+ processAppUninstall(buffer, send, creds);
+ break;
+ case SecurityModuleCall::APP_GET_PKG_NAME:
+ LogDebug("call_type: SecurityModuleCall::APP_GET_PKG_NAME");
+ processGetPkgName(buffer, send);
+ break;
+ case SecurityModuleCall::USER_ADD:
+ LogDebug("call_type: SecurityModuleCall::USER_ADD");
+ processUserAdd(buffer, send, creds);
+ break;
+ case SecurityModuleCall::USER_DELETE:
+ LogDebug("call_type: SecurityModuleCall::USER_DELETE");
+ processUserDelete(buffer, send, creds);
+ break;
+ case SecurityModuleCall::POLICY_UPDATE:
+ LogDebug("call_type: SecurityModuleCall::POLICY_UPDATE");
+ processPolicyUpdate(buffer, send, creds);
+ break;
+ case SecurityModuleCall::GET_CONF_POLICY_ADMIN:
+ LogDebug("call_type: SecurityModuleCall::GET_CONF_POLICY_ADMIN");
+ processGetConfiguredPolicy(buffer, send, creds, true);
+ break;
+ case SecurityModuleCall::GET_CONF_POLICY_SELF:
+ LogDebug("call_type: SecurityModuleCall::GET_CONF_POLICY_SELF");
+ processGetConfiguredPolicy(buffer, send, creds, false);
+ break;
+ case SecurityModuleCall::GET_POLICY:
+ LogDebug("call_type: SecurityModuleCall::GET_POLICY");
+ processGetPolicy(buffer, send, creds);
+ break;
+ case SecurityModuleCall::POLICY_GET_DESCRIPTIONS:
+ LogDebug("call_type: SecurityModuleCall::POLICY_GET_DESCRIPTIONS");
+ processPolicyGetDesc(send);
+ break;
+ case SecurityModuleCall::GROUPS_GET:
+ LogDebug("call_type: SecurityModuleCall::GROUPS_GET");
+ processGetForbiddenAndAllowedGroups(buffer, send, creds);
+ break;
+ case SecurityModuleCall::GROUPS_FOR_UID:
+ processGroupsForUid(buffer, send);
+ break;
+ case SecurityModuleCall::APP_HAS_PRIVILEGE:
+ LogDebug("call_type: SecurityModuleCall::APP_HAS_PRIVILEGE");
+ processAppHasPrivilege(buffer, send, creds);
+ break;
+ case SecurityModuleCall::APP_APPLY_PRIVATE_SHARING:
+ LogDebug("call_type: SecurityModuleCall::APP_APPLY_PRIVATE_SHARING");
+ processApplyPrivateSharing(buffer, send, creds);
+ break;
+ case SecurityModuleCall::APP_DROP_PRIVATE_SHARING:
+ LogDebug("call_type: SecurityModuleCall::APP_DROP_PRIVATE_SHARING");
+ processDropPrivateSharing(buffer, send, creds);
+ break;
+ case SecurityModuleCall::PATHS_REGISTER:
+ processPathsRegister(buffer, send, creds);
+ break;
+ case SecurityModuleCall::SHM_APP_NAME:
+ processShmAppName(buffer, send, creds);
+ break;
+ case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER:
+ LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER");
+ processGetAppDefinedPrivilegeProvider(buffer, send);
+ break;
+ case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE:
+ LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE");
+ processGetAppDefinedPrivilegeLicense(buffer, send);
+ break;
+ case SecurityModuleCall::GET_CLIENT_PRIVILEGE_LICENSE:
+ LogDebug("call_type: SecurityModuleCall::GET_CLIENT_PRIVILEGE_PROVIDER");
+ processGetClientPrivilegeLicense(buffer, send);
+ break;
+ case SecurityModuleCall::APP_CLEAN_NAMESPACE:
+ LogDebug("call_type: SecurityModuleCall::APP_CLEAN_NAMESPACE");
+ processAppCleanNamespace(buffer, send, creds);
+ break;
+ case SecurityModuleCall::GET_APP_MANIFEST_POLICY:
+ LogDebug("call_type: SecurityModuleCall::GET_APP_MANIFEST_POLICY");
+ processAppGetManifestPolicy(buffer, send, creds);
+ break;
+ case SecurityModuleCall::GET_PROCESS_LABEL:
+ processGetProcessLabel(buffer, send);
+ break;
+ case SecurityModuleCall::PREPARE_APP:
+ prepareApp(buffer, send, creds);
+ break;
+ default:
+ LogError("Invalid call: " << call_type_int);
+ Throw(ServiceException::InvalidAction);
+ }
+ // if we reach this point, the protocol is OK
LogDebug("Writing response to client, size of serialized response: " << send.SerializedSize());
m_serviceManager->Write(conn, send.Pop());
- } else {
- LogError("Closing socket because of error");
- m_serviceManager->Close(conn);
+ return true;
+ } Catch(MessageBuffer::Exception::Base) {
+ LogError("Broken protocol.");
+ } Catch(ServiceException::Base) {
+ LogError("Broken protocol.");
+ } catch (const std::exception &e) {
+ LogError("STD exception " << e.what());
+ } catch (...) {
+ LogError("Unknown exception");
}
- return retval;
+ LogError("Closing socket because of error");
+ m_serviceManager->Close(conn);
+
+ return false;
}
void Service::processAppGetManifestPolicy(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)