#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>
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;
+ });
+}
+
${COMMON_DEP_LIBRARIES}
${DLOG_DEP_LIBRARIES}
-lcrypt
+ rt
)
INSTALL(TARGETS ${TARGET_COMMON} DESTINATION ${LIB_INSTALL_DIR})
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";
*/
#include <unistd.h>
+#include <sys/stat.h>
#include <sys/socket.h>
#include "smack-check.h"
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
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;
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:
PATHS_REGISTER,
GROUPS_FOR_UID,
LABEL_FOR_PROCESS,
+ SHM_APP_NAME,
NOOP = 0x90,
};
* @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);
Cynara m_cynara;
PrivilegeDb m_priviligeDb;
CynaraAdmin m_cynaraAdmin;
-
};
} /* namespace SecurityManager */
#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>
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 */
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
* @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
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);
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