diff options
author | Bartlomiej Grzelewski <b.grzelewski@samsung.com> | 2016-06-13 12:06:19 +0200 |
---|---|---|
committer | Rafal Krypa <r.krypa@samsung.com> | 2016-11-29 16:58:06 +0100 |
commit | 20f18f36ad5ded17a45bcc1ee59f67c4e77a4809 (patch) | |
tree | 62505c147120b3fee8b83c5e8bf3e7dc70b68cb2 | |
parent | 082a1731302c5e161e5d52eace72cfe46e7794ea (diff) | |
download | security-manager-20f18f36ad5ded17a45bcc1ee59f67c4e77a4809.tar.gz security-manager-20f18f36ad5ded17a45bcc1ee59f67c4e77a4809.tar.bz2 security-manager-20f18f36ad5ded17a45bcc1ee59f67c4e77a4809.zip |
Add security_manager_shm_open
This function will create file that may be used
by shm_open and mmap functions. If the file
exists noting is done.
Change-Id: Ifdfdf15df96fb67faa4340d113445527c77ba60f
-rw-r--r-- | src/client/client-security-manager.cpp | 63 | ||||
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/config.cpp | 1 | ||||
-rw-r--r-- | src/common/credentials.cpp | 10 | ||||
-rw-r--r-- | src/common/include/config.h | 1 | ||||
-rw-r--r-- | src/common/include/credentials.h | 2 | ||||
-rw-r--r-- | src/common/include/protocols.h | 1 | ||||
-rw-r--r-- | src/common/include/service_impl.h | 14 | ||||
-rw-r--r-- | src/common/service_impl.cpp | 57 | ||||
-rw-r--r-- | src/include/app-runtime.h | 14 | ||||
-rw-r--r-- | src/server/service/include/service.h | 9 | ||||
-rw-r--r-- | src/server/service/service.cpp | 12 |
12 files changed, 184 insertions, 1 deletions
diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index c3981465..82c2407f 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -38,12 +38,14 @@ #include <unistd.h> #include <grp.h> #include <dirent.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/xattr.h> #include <sys/smack.h> #include <sys/capability.h> #include <sys/syscall.h> +#include <sys/mman.h> #include <signal.h> #include <dpl/log/log.h> @@ -1515,3 +1517,64 @@ int security_manager_paths_register(const path_req *p_req) return retval; }); } + +SECURITY_MANAGER_API +int security_manager_shm_open(const char *name, int oflag, mode_t mode, const char *app_name) +{ + using namespace SecurityManager; + return try_catch([&]() -> int { + if (!name || !app_name) { + errno = EINVAL; + return -1; + } + + int fd = shm_open(name, oflag, mode); + if (fd < 0) + return -1; + + auto scopeClose = makeUnique(&fd, [](int *ptr) -> void { if (*ptr >= 0) close(*ptr); }); + + MessageBuffer send, recv; + Serialization::Serialize(send, + (int)SecurityModuleCall::SHM_APP_NAME, + std::string(name), + std::string(app_name)); + + int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv); + if (retval != SECURITY_MANAGER_SUCCESS) { + // Let's propagate errno + LogError("Error in sendToServer. Error code: " << retval); + return -1; + } + + Deserialization::Deserialize(recv, retval); + switch(retval) { + case SECURITY_MANAGER_SUCCESS: + scopeClose.release(); + return fd; + case SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED: + LogError("Error: operation not permitted"); + errno = EPERM; + break; + case SECURITY_MANAGER_ERROR_ACCESS_DENIED: + LogError("Error access denied"); + errno = EACCES; + break; + case SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT: + case SECURITY_MANAGER_ERROR_INPUT_PARAM: + LogError("Error input param"); + errno = EINVAL; + break; + case SECURITY_MANAGER_ERROR_MEMORY: + LogError("Error memory allocation"); + errno = ENOMEM; + break; + default: + LogError("Error internal security-manager error"); + errno = ECONNABORTED; + break; + } + return -1; + }); +} + diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index bff232c1..a91ed2df 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -88,6 +88,7 @@ TARGET_LINK_LIBRARIES(${TARGET_COMMON} ${COMMON_DEP_LIBRARIES} ${DLOG_DEP_LIBRARIES} -lcrypt + rt ) INSTALL(TARGETS ${TARGET_COMMON} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/common/config.cpp b/src/common/config.cpp index fa12770d..2f38867c 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -36,6 +36,7 @@ const std::string PRIVILEGE_USER_ADMIN = "http://tizen.org/privilege/inter const std::string PRIVILEGE_POLICY_USER = "http://tizen.org/privilege/notexist"; const std::string PRIVILEGE_POLICY_ADMIN = "http://tizen.org/privilege/internal/usermanagement"; const std::string PRIVILEGE_APPSHARING_ADMIN = "http://tizen.org/privilege/notexist"; +const std::string PRIVILEGE_SHM = "http://tizen.org/privilege/internal/shm"; const std::string APPS_LABELS_FILE = "apps-labels"; const std::string SKEL_DIR = "/etc/skel"; diff --git a/src/common/credentials.cpp b/src/common/credentials.cpp index 9bf8d708..c0640a75 100644 --- a/src/common/credentials.cpp +++ b/src/common/credentials.cpp @@ -20,6 +20,7 @@ */ #include <unistd.h> +#include <sys/stat.h> #include <sys/socket.h> #include "smack-check.h" @@ -45,4 +46,13 @@ Credentials Credentials::getCredentialsFromSocket(int sock) return Credentials(cr.pid, cr.uid, cr.gid, SmackLabels::getSmackLabelFromSocket(sock)); } +Credentials Credentials::getCredentialsFromFd(int fd) +{ + struct stat buf; + if (-1 == fstat(fd, &buf)) + ThrowMsg(Exception::FdError, "Failed to read credentials from filefd " << fd); + + return Credentials(-1, buf.st_uid, buf.st_gid, SmackLabels::getSmackLabelFromFd(fd)); +} + } // namespace SecurityManager diff --git a/src/common/include/config.h b/src/common/include/config.h index ab3c78f2..f8ac57a3 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -40,6 +40,7 @@ extern const std::string PRIVILEGE_USER_ADMIN; extern const std::string PRIVILEGE_POLICY_USER; extern const std::string PRIVILEGE_POLICY_ADMIN; extern const std::string PRIVILEGE_APPSHARING_ADMIN; +extern const std::string PRIVILEGE_SHM; /* Files used in permitted label managment */ extern const std::string APPS_LABELS_FILE; diff --git a/src/common/include/credentials.h b/src/common/include/credentials.h index ea0b0b20..f8a7dce5 100644 --- a/src/common/include/credentials.h +++ b/src/common/include/credentials.h @@ -39,11 +39,13 @@ public: Credentials() = delete; static Credentials getCredentialsFromSelf(void); static Credentials getCredentialsFromSocket(int socket); + static Credentials getCredentialsFromFd(int fd); class Exception { public: DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base) DECLARE_EXCEPTION_TYPE(Base, SocketError) + DECLARE_EXCEPTION_TYPE(Base, FdError) }; private: diff --git a/src/common/include/protocols.h b/src/common/include/protocols.h index c93fb14a..fcf13141 100644 --- a/src/common/include/protocols.h +++ b/src/common/include/protocols.h @@ -87,6 +87,7 @@ enum class SecurityModuleCall PATHS_REGISTER, GROUPS_FOR_UID, LABEL_FOR_PROCESS, + SHM_APP_NAME, NOOP = 0x90, }; diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index 9a7f7e73..84177fb5 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -234,6 +234,19 @@ public: * @return API return code, as defined in protocols.h */ int labelForProcess(const std::string &appName, std::string &label); + /* + * Request for access to shared memory segment for + * appName application. + * + * @param[in] creds credentials of the requesting process + * @param[in] name shared memory identifier + * @param[in] appName application identifier + * + * @return API return code, as defined in protocols.h + */ + int shmAppName(const Credentials &creds, + const std::string &shmName, + const std::string &appName); private: bool authenticate(const Credentials &creds, const std::string &privilege); @@ -299,7 +312,6 @@ private: Cynara m_cynara; PrivilegeDb m_priviligeDb; CynaraAdmin m_cynaraAdmin; - }; } /* namespace SecurityManager */ diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index a8ac5896..54a27fdb 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -29,6 +29,7 @@ #include <linux/xattr.h> #include <limits.h> #include <pwd.h> +#include <sys/mman.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> @@ -1648,4 +1649,60 @@ int ServiceImpl::labelForProcess(const std::string &appName, std::string &label) return SECURITY_MANAGER_SUCCESS; } +int ServiceImpl::shmAppName(const Credentials &creds, const std::string &shmName, const std::string &appName) +{ + try { + if (shmName.empty() || appName.empty()) + return SECURITY_MANAGER_ERROR_INPUT_PARAM; + + if (!PrivilegeDb::getInstance().AppNameExists(appName)) { + LogError("Unknown application id: " << appName); + return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT; + } + + if (!authenticate(creds, Config::PRIVILEGE_SHM)) { + LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << " for shm denied"); + return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; + } + + std::string label = getAppProcessLabel(appName); + + int fd = shm_open(shmName.c_str(), O_RDWR, 0); + if (fd < 0) { + LogError("Error in shm_open"); + return SECURITY_MANAGER_ERROR_INPUT_PARAM; + } + + auto scopeClose = makeUnique(&fd, [](int *ptr) -> void { if (*ptr >= 0) close(*ptr);}); + + Credentials fdCreds = Credentials::getCredentialsFromFd(fd); + + if (fdCreds.label == label) { + // Nothing to do. The file already has proper label. + // Client called this function twice? + LogDebug("Noting to do. File have already label: " << label << " The client probably called this api twice."); + return SECURITY_MANAGER_SUCCESS; + } + + if ((creds.label != fdCreds.label) || (creds.uid != fdCreds.uid)) { + LogDebug("Client (smack: " << creds.label <<", pid: " << creds.pid + << ") does not have permission to access shared memory file (segment name: " + << shmName << ")."); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + + SmackLabels::setSmackLabelForFd(fd, label); + } catch (const CynaraException::Base &e) { + LogError("Error while querying Cynara for permissions: " << e.DumpToString()); + return SECURITY_MANAGER_ERROR_SERVER_ERROR; + } catch (const SmackException::Base &e) { + LogError("Error while set/get smack label in /dev/shm: " << e.DumpToString()); + return SECURITY_MANAGER_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + LogError("Memory allocation failed: " << e.what()); + return SECURITY_MANAGER_ERROR_MEMORY; + } + return SECURITY_MANAGER_SUCCESS; +} + } /* namespace SecurityManager */ diff --git a/src/include/app-runtime.h b/src/include/app-runtime.h index ee4d2de5..6e1f03b3 100644 --- a/src/include/app-runtime.h +++ b/src/include/app-runtime.h @@ -205,6 +205,20 @@ int security_manager_identify_app_from_cynara_client(const char *client, char ** int security_manager_app_has_privilege(const char *app_id, const char *privilege, uid_t uid, int *result); +/** + * This function creates descriptor that may be used as shared memory segment + * with app_id application. + * + * \param[in] name This value is passed to shm_open as first parameter (man 3 shm_open for details) + * \param[in] oflag This value is passed to shm_open as second parameter (man 3 shm_open for details) + * \param[in] mode This value is passed to shm_open as third parameter (man 3 shm_open for details) + * \param[in] app_id Identifier of application that will gain access to shared memory segment + * \return file descriptor or -1 on error. If -1 is returned then errno will be set. Errno == ECONNABORTED + * means that the security-manager server failed and did not return any information + * about error. + */ +int security_manager_shm_open(const char *name, int oflag, mode_t mode, const char *app_id); + #ifdef __cplusplus } #endif diff --git a/src/server/service/include/service.h b/src/server/service/include/service.h index aed44d8b..a1eeb4dc 100644 --- a/src/server/service/include/service.h +++ b/src/server/service/include/service.h @@ -194,6 +194,15 @@ private: * @param send Raw data buffer to be sent */ void processLabelForProcess(MessageBuffer &buffer, MessageBuffer &send); + + /** + * Process shared memory access request + * + * @param recv Raw received data buffer + * @param send Raw data buffer to be sent + * @param creds credentials of the requesting process + */ + void processShmAppName(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds); }; } // namespace SecurityManager diff --git a/src/server/service/service.cpp b/src/server/service/service.cpp index 04322424..fe4f865b 100644 --- a/src/server/service/service.cpp +++ b/src/server/service/service.cpp @@ -147,6 +147,9 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, case SecurityModuleCall::LABEL_FOR_PROCESS: processLabelForProcess(buffer, send); break; + case SecurityModuleCall::SHM_APP_NAME: + processShmAppName(buffer, send, creds); + break; default: LogError("Invalid call: " << call_type_int); Throw(ServiceException::InvalidAction); @@ -406,4 +409,13 @@ void Service::processLabelForProcess(MessageBuffer &buffer, MessageBuffer &send) if (ret == SECURITY_MANAGER_SUCCESS) Serialization::Serialize(send, label); } + +void Service::processShmAppName(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds) +{ + std::string shmName, appName; + Deserialization::Deserialize(recv, shmName, appName); + int ret = serviceImpl.shmAppName(creds, shmName, appName); + Serialization::Serialize(send, ret); +} + } // namespace SecurityManager |