summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>2016-06-13 12:06:19 +0200
committerRafal Krypa <r.krypa@samsung.com>2016-11-29 16:58:06 +0100
commit20f18f36ad5ded17a45bcc1ee59f67c4e77a4809 (patch)
tree62505c147120b3fee8b83c5e8bf3e7dc70b68cb2
parent082a1731302c5e161e5d52eace72cfe46e7794ea (diff)
downloadsecurity-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.cpp63
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/config.cpp1
-rw-r--r--src/common/credentials.cpp10
-rw-r--r--src/common/include/config.h1
-rw-r--r--src/common/include/credentials.h2
-rw-r--r--src/common/include/protocols.h1
-rw-r--r--src/common/include/service_impl.h14
-rw-r--r--src/common/service_impl.cpp57
-rw-r--r--src/include/app-runtime.h14
-rw-r--r--src/server/service/include/service.h9
-rw-r--r--src/server/service/service.cpp12
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