/* * ModSecurity, http://www.modsecurity.org/ * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) * * You may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * If any of the files related to licensing are missing or if you have any * other questions related to licensing please contact Trustwave Holdings, Inc. * directly using the email address security@modsecurity.org. * */ #include "src/utils/shared_files.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace modsecurity { namespace utils { std::pair SharedFiles::find_handler( const std::string &fileName) { for (const auto &i : m_handlers) { if (i.first == fileName) { return i.second; } } return std::pair(NULL, NULL); } std::pair SharedFiles::add_new_handler( const std::string &fileName, std::string *error) { int shm_id; int ret; key_t mem_key_structure; msc_file_handler_t *new_debug_log; struct shmid_ds shared_mem_info; FILE *fp; bool toBeCreated = true; fp = fopen(fileName.c_str(), "a"); if (fp == 0) { error->assign("Failed to open file: " + fileName); goto err_fh; } mem_key_structure = ftok(fileName.c_str(), 1); if (mem_key_structure < 0) { error->assign("Failed to select key for the shared memory (1): "); error->append(strerror(errno)); goto err_mem_key; } shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) \ + fileName.size() + 1, IPC_CREAT | IPC_EXCL | 0666); if (shm_id < 0) { shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) + fileName.size() + 1, IPC_CREAT | 0666); toBeCreated = false; if (shm_id < 0) { error->assign("Failed to allocate shared memory (1): "); error->append(strerror(errno)); goto err_shmget1; } } ret = shmctl(shm_id, IPC_STAT, &shared_mem_info); if (ret < 0) { error->assign("Failed to get information on shared memory (1): "); error->append(strerror(errno)); goto err_shmctl1; } new_debug_log = reinterpret_cast( shmat(shm_id, NULL, 0)); if ((reinterpret_cast(new_debug_log)[0]) == -1) { error->assign("Failed to attach shared memory (1): "); error->append(strerror(errno)); goto err_shmat1; } if (toBeCreated == false && shared_mem_info.shm_nattch == 0) { toBeCreated = true; } if (toBeCreated) { memset(new_debug_log, '\0', sizeof(msc_file_handler_t)); pthread_mutex_init(&new_debug_log->lock, NULL); new_debug_log->shm_id_structure = shm_id; memcpy(new_debug_log->file_name, fileName.c_str(), fileName.size()); new_debug_log->file_name[fileName.size()] = '\0'; } m_handlers.push_back(std::make_pair(fileName, std::make_pair(new_debug_log, fp))); return std::make_pair(new_debug_log, fp); err_shmget1: err_shmctl1: err_shmat1: shmdt(new_debug_log); err_mem_key: fclose(fp); err_fh: return std::pair(NULL, NULL); } bool SharedFiles::open(const std::string& fileName, std::string *error) { std::pair a; #if MODSEC_USE_GENERAL_LOCK pthread_mutex_lock(m_generalLock); #endif a = find_handler(fileName); if (a.first == NULL) { a = add_new_handler(fileName, error); if (error->size() > 0) { goto out; } } if (a.first == NULL) { error->assign("Not able to open: " + fileName); goto out; } out: #if MODSEC_USE_GENERAL_LOCK pthread_mutex_unlock(m_generalLock); #endif return true; } void SharedFiles::close(const std::string& fileName) { std::pair a; /* int ret; */ /* int shm_id; */ /* struct shmid_ds shared_mem_info; */ /* int j = 0; */ #if MODSEC_USE_GENERAL_LOCK pthread_mutex_lock(m_generalLock); #endif if (fileName.empty()) { goto out; } a = find_handler(fileName); if (a.first == NULL || a.second == NULL) { goto out; } /* fclose(a.second); */ a.second = 0; /* * Delete the file structure will be welcomed, but we cannot delay * while the process is being killed. * for (std::pair> i : m_handlers) { if (i.first == fileName) { j++; } } m_handlers.erase(m_handlers.begin()+j); */ /* hmdt(a.second); */ shmctl(a.first->shm_id_structure, IPC_RMID, NULL); /* * * We could check to see how many process attached to the shared memory * we have, prior to the deletion of the shared memory. * ret = shmctl(a.first->shm_id_structure, IPC_STAT, &shared_mem_info); if (ret < 0) { goto out; } ret = shared_mem_info.shm_nattch; shm_id = a.first->shm_id_structure; */ out: #if MODSEC_USE_GENERAL_LOCK pthread_mutex_unlock(m_generalLock); #endif return; } bool SharedFiles::write(const std::string& fileName, const std::string &msg, std::string *error) { std::pair a; std::string lmsg = msg; size_t wrote; bool ret = true; a = find_handler(fileName); if (a.first == NULL) { error->assign("file is not open: " + fileName); return false; } pthread_mutex_lock(&a.first->lock); wrote = fwrite(reinterpret_cast(lmsg.c_str()), 1, lmsg.size(), a.second); if (wrote < msg.size()) { error->assign("failed to write: " + fileName); ret = false; } fflush(a.second); pthread_mutex_unlock(&a.first->lock); return ret; } } // namespace utils } // namespace modsecurity