diff options
| author | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-08-10 10:21:25 +0200 |
|---|---|---|
| committer | Nikola Pajkovsky <npajkovs@redhat.com> | 2010-08-10 10:21:56 +0200 |
| commit | 83a6ce9ad4b1828e163dc7172ef603201b748473 (patch) | |
| tree | 9d0580eba6c01cb5964655df42bafab9de91329b /lib/Utils/DebugDump.cpp | |
| parent | e84ab7783d05eb7b5f1b55ab44e7c23c85e50516 (diff) | |
| download | abrt-83a6ce9ad4b1828e163dc7172ef603201b748473.tar.gz abrt-83a6ce9ad4b1828e163dc7172ef603201b748473.tar.xz abrt-83a6ce9ad4b1828e163dc7172ef603201b748473.zip | |
lower case direcotry(no code changed)
Signed-off-by: Nikola Pajkovsky <npajkovs@redhat.com>
Diffstat (limited to 'lib/Utils/DebugDump.cpp')
| -rw-r--r-- | lib/Utils/DebugDump.cpp | 521 |
1 files changed, 0 insertions, 521 deletions
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp deleted file mode 100644 index 30ceacc1..00000000 --- a/lib/Utils/DebugDump.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* - DebugDump.cpp - - Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 RedHat inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include <sys/utsname.h> -#include "abrtlib.h" -#include "debug_dump.h" -#include "abrt_exception.h" -#include "comm_layer_inner.h" - -static bool isdigit_str(const char *str) -{ - do - { - if (*str < '0' || *str > '9') return false; - str++; - } while (*str); - return true; -} - -static std::string RemoveBackSlashes(const char *pDir) -{ - unsigned len = strlen(pDir); - while (len != 0 && pDir[len-1] == '/') - len--; - return std::string(pDir, len); -} - -static bool ExistFileDir(const char *pPath) -{ - struct stat buf; - if (stat(pPath, &buf) == 0) - { - if (S_ISDIR(buf.st_mode) || S_ISREG(buf.st_mode)) - { - return true; - } - } - return false; -} - -static void LoadTextFile(const char *pPath, std::string& pData); - -CDebugDump::CDebugDump() : - m_sDebugDumpDir(""), - m_pGetNextFileDir(NULL), - m_bOpened(false), - m_bLocked(false), - m_uid(0), - m_gid(0) -{} - -CDebugDump::~CDebugDump() -{ - /* Paranoia. In C++, destructor will abort() if it was called while unwinding - * the stack and it throws an exception. - */ - try - { - Close(); - m_sDebugDumpDir.clear(); - } - catch (...) - { - error_msg_and_die("Internal error"); - } -} - -void CDebugDump::Open(const char *pDir) -{ - if (m_bOpened) - { - throw CABRTException(EXCEP_ERROR, "CDebugDump is already opened"); - } - m_sDebugDumpDir = RemoveBackSlashes(pDir); - if (!ExistFileDir(m_sDebugDumpDir.c_str())) - { - throw CABRTException(EXCEP_DD_OPEN, "'%s' does not exist", m_sDebugDumpDir.c_str()); - } - Lock(); - m_bOpened = true; - /* In case caller would want to create more files, he'll need uid:gid */ - m_uid = 0; - m_gid = 0; - struct stat stat_buf; - if (stat(m_sDebugDumpDir.c_str(), &stat_buf) == 0) - { - m_uid = stat_buf.st_uid; - m_gid = stat_buf.st_gid; - } -} - -bool CDebugDump::Exist(const char* pPath) -{ - std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pPath); - return ExistFileDir(fullPath.c_str()); -} - -static bool GetAndSetLock(const char* pLockFile, const char* pPID) -{ - while (symlink(pPID, pLockFile) != 0) - { - if (errno != EEXIST) - perror_msg_and_die("Can't create lock file '%s'", pLockFile); - - char pid_buf[sizeof(pid_t)*3 + 4]; - ssize_t r = readlink(pLockFile, pid_buf, sizeof(pid_buf) - 1); - if (r < 0) - { - if (errno == ENOENT) - { - /* Looks like pLockFile was deleted */ - usleep(10 * 1000); /* avoid CPU eating loop */ - continue; - } - perror_msg_and_die("Can't read lock file '%s'", pLockFile); - } - pid_buf[r] = '\0'; - - if (strcmp(pid_buf, pPID) == 0) - { - log("Lock file '%s' is already locked by us", pLockFile); - return false; - } - if (isdigit_str(pid_buf)) - { - if (access(ssprintf("/proc/%s", pid_buf).c_str(), F_OK) == 0) - { - log("Lock file '%s' is locked by process %s", pLockFile, pid_buf); - return false; - } - log("Lock file '%s' was locked by process %s, but it crashed?", pLockFile, pid_buf); - } - /* The file may be deleted by now by other process. Ignore ENOENT */ - if (unlink(pLockFile) != 0 && errno != ENOENT) - { - perror_msg_and_die("Can't remove stale lock file '%s'", pLockFile); - } - } - - VERB1 log("Locked '%s'", pLockFile); - return true; - -#if 0 -/* Old code was using ordinary files instead of symlinks, - * but it had a race window between open and write, during which file was - * empty. It was seen to happen in practice. - */ - int fd; - while ((fd = open(pLockFile, O_WRONLY | O_CREAT | O_EXCL, 0640)) < 0) - { - if (errno != EEXIST) - perror_msg_and_die("Can't create lock file '%s'", pLockFile); - fd = open(pLockFile, O_RDONLY); - if (fd < 0) - { - if (errno == ENOENT) - continue; /* someone else deleted the file */ - perror_msg_and_die("Can't open lock file '%s'", pLockFile); - } - char pid_buf[sizeof(pid_t)*3 + 4]; - int r = read(fd, pid_buf, sizeof(pid_buf) - 1); - if (r < 0) - perror_msg_and_die("Can't read lock file '%s'", pLockFile); - close(fd); - if (r == 0) - { - /* Other process did not write out PID yet. - * We HOPE it did not crash... */ - continue; - } - pid_buf[r] = '\0'; - if (strcmp(pid_buf, pPID) == 0) - { - log("Lock file '%s' is already locked by us", pLockFile); - return -1; - } - if (isdigit_str(pid_buf)) - { - if (access(ssprintf("/proc/%s", pid_buf).c_str(), F_OK) == 0) - { - log("Lock file '%s' is locked by process %s", pLockFile, pid_buf); - return -1; - } - log("Lock file '%s' was locked by process %s, but it crashed?", pLockFile, pid_buf); - } - /* The file may be deleted by now by other process. Ignore errors */ - unlink(pLockFile); - } - - int len = strlen(pPID); - if (write(fd, pPID, len) != len) - { - unlink(pLockFile); - /* close(fd); - not needed, exiting does it too */ - perror_msg_and_die("Can't write lock file '%s'", pLockFile); - } - close(fd); - - VERB1 log("Locked '%s'", pLockFile); - return true; -#endif -} - -void CDebugDump::Lock() -{ - if (m_bLocked) - error_msg_and_die("Locking bug on '%s'", m_sDebugDumpDir.c_str()); - - std::string lockFile = m_sDebugDumpDir + ".lock"; - char pid_buf[sizeof(long)*3 + 2]; - sprintf(pid_buf, "%lu", (long)getpid()); - while ((m_bLocked = GetAndSetLock(lockFile.c_str(), pid_buf)) != true) - { - sleep(1); /* was 0.5 seconds */ - } -} - -void CDebugDump::UnLock() -{ - if (m_bLocked) - { - m_bLocked = false; - std::string lockFile = m_sDebugDumpDir + ".lock"; - xunlink(lockFile.c_str()); - VERB1 log("UnLocked '%s'", lockFile.c_str()); - } -} - -/* Create a fresh empty debug dump dir. - * - * Security: we should not allow users to write new files or write - * into existing ones, but they should be able to read them. - * - * @param uid - * Crashed application's User Id - * - * We currently have only three callers: - * kernel oops hook: uid=0 - * this hook runs under 0:0 - * ccpp hook: uid=uid of crashed user's binary - * this hook runs under 0:0 - * python hook: uid=uid of crashed user's script - * this hook runs under abrt:gid - * - * Currently, we set dir's gid to passwd(uid)->pw_gid parameter, and we set uid to - * abrt's user id. We do not allow write access to group. - */ -void CDebugDump::Create(const char *pDir, uid_t uid) -{ - if (m_bOpened) - { - throw CABRTException(EXCEP_ERROR, "DebugDump is already opened"); - } - - m_sDebugDumpDir = RemoveBackSlashes(pDir); - if (ExistFileDir(m_sDebugDumpDir.c_str())) - { - throw CABRTException(EXCEP_DD_OPEN, "'%s' already exists", m_sDebugDumpDir.c_str()); - } - - Lock(); - m_bOpened = true; - - /* Was creating it with mode 0700 and user as the owner, but this allows - * the user to replace any file in the directory, changing security-sensitive data - * (e.g. "uid", "analyzer", "executable") - */ - if (mkdir(m_sDebugDumpDir.c_str(), 0750) == -1) - { - UnLock(); - m_bOpened = false; - throw CABRTException(EXCEP_DD_OPEN, "Can't create dir '%s'", pDir); - } - - /* mkdir's mode (above) can be affected by umask, fix it */ - if (chmod(m_sDebugDumpDir.c_str(), 0750) == -1) - { - UnLock(); - m_bOpened = false; - throw CABRTException(EXCEP_DD_OPEN, "Can't change mode of '%s'", pDir); - } - - /* Get ABRT's user id */ - m_uid = 0; - struct passwd *pw = getpwnam("abrt"); - if (pw) - m_uid = pw->pw_uid; - else - error_msg("User 'abrt' does not exist, using uid 0"); - - /* Get crashed application's group id */ - m_gid = 0; - pw = getpwuid(uid); - if (pw) - m_gid = pw->pw_gid; - else - error_msg("User %lu does not exist, using gid 0", (long)uid); - - if (chown(m_sDebugDumpDir.c_str(), m_uid, m_gid) == -1) - { - perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(), - (long)m_uid, (long)m_gid); - } - - SaveText(CD_UID, to_string(uid).c_str()); - - { - struct utsname buf; - if (uname(&buf) != 0) - { - perror_msg_and_die("uname"); - } - SaveText(FILENAME_KERNEL, buf.release); - SaveText(FILENAME_ARCHITECTURE, buf.machine); - std::string release; - LoadTextFile("/etc/redhat-release", release); - const char *release_ptr = release.c_str(); - unsigned len_1st_str = strchrnul(release_ptr, '\n') - release_ptr; - release.erase(len_1st_str); /* usually simply removes trailing '\n' */ - SaveText(FILENAME_RELEASE, release.c_str()); - } - - time_t t = time(NULL); - SaveText(FILENAME_TIME, to_string(t).c_str()); -} - -static void DeleteFileDir(const char *pDir) -{ - DIR *dir = opendir(pDir); - if (!dir) - return; - - struct dirent *dent; - while ((dent = readdir(dir)) != NULL) - { - if (dot_or_dotdot(dent->d_name)) - continue; - std::string fullPath = concat_path_file(pDir, dent->d_name); - if (unlink(fullPath.c_str()) == -1) - { - if (errno != EISDIR) - { - closedir(dir); - throw CABRTException(EXCEP_DD_DELETE, "Can't remove dir %s", fullPath.c_str()); - } - DeleteFileDir(fullPath.c_str()); - } - } - closedir(dir); - if (rmdir(pDir) == -1) - { - throw CABRTException(EXCEP_DD_DELETE, "Can't remove dir %s", pDir); - } -} - -void CDebugDump::Delete() -{ - if (!ExistFileDir(m_sDebugDumpDir.c_str())) - { - return; - } - DeleteFileDir(m_sDebugDumpDir.c_str()); -} - -void CDebugDump::Close() -{ - UnLock(); - if (m_pGetNextFileDir != NULL) - { - closedir(m_pGetNextFileDir); - m_pGetNextFileDir = NULL; - } - m_bOpened = false; -} - -static void LoadTextFile(const char *pPath, std::string& pData) -{ - FILE *fp = fopen(pPath, "r"); - if (!fp) - { - throw CABRTException(EXCEP_DD_LOAD, "Can't open file '%s'", pPath); - } - pData = ""; - int ch; - while ((ch = fgetc(fp)) != EOF) - { - if (ch == '\0') - { - pData += ' '; - } - else if (isspace(ch) || (isascii(ch) && !iscntrl(ch))) - { - pData += ch; - } - } - fclose(fp); -} - -static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize, uid_t uid, gid_t gid) -{ - /* "Why 0640?!" See ::Create() for security analysis */ - unlink(pPath); - int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0640); - if (fd < 0) - { - throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s': %s", pPath, errno ? strerror(errno) : "errno == 0"); - } - if (fchown(fd, uid, gid) == -1) - { - perror_msg("can't change '%s' ownership to %lu:%lu", pPath, (long)uid, (long)gid); - } - unsigned r = full_write(fd, pData, pSize); - close(fd); - if (r != pSize) - { - throw CABRTException(EXCEP_DD_SAVE, "Can't save file '%s'", pPath); - } -} - -void CDebugDump::LoadText(const char* pName, std::string& pData) -{ - if (!m_bOpened) - { - throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened"); - } - std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName); - LoadTextFile(fullPath.c_str(), pData); -} - -void CDebugDump::SaveText(const char* pName, const char* pData) -{ - if (!m_bOpened) - { - throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened"); - } - std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName); - SaveBinaryFile(fullPath.c_str(), pData, strlen(pData), m_uid, m_gid); -} - -void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize) -{ - if (!m_bOpened) - { - throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened"); - } - std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName); - SaveBinaryFile(fullPath.c_str(), pData, pSize, m_uid, m_gid); -} - -void CDebugDump::InitGetNextFile() -{ - if (!m_bOpened) - { - throw CABRTException(EXCEP_DD_OPEN, "DebugDump is not opened"); - } - if (m_pGetNextFileDir != NULL) - { - closedir(m_pGetNextFileDir); - } - m_pGetNextFileDir = opendir(m_sDebugDumpDir.c_str()); - if (m_pGetNextFileDir == NULL) - { - throw CABRTException(EXCEP_DD_OPEN, "Can't open dir '%s'", m_sDebugDumpDir.c_str()); - } -} - -bool CDebugDump::GetNextFile(std::string *short_name, std::string *full_name) -{ - if (m_pGetNextFileDir == NULL) - { - return false; - } - - struct dirent *dent; - while ((dent = readdir(m_pGetNextFileDir)) != NULL) - { - if (is_regular_file(dent, m_sDebugDumpDir.c_str())) - { - if (short_name) - *short_name = dent->d_name; - if (full_name) - *full_name = concat_path_file(m_sDebugDumpDir.c_str(), dent->d_name); - return true; - } - } - closedir(m_pGetNextFileDir); - m_pGetNextFileDir = NULL; - return false; -} - -/* Utility function */ -void delete_debug_dump_dir(const char *pDebugDumpDir) -{ - try - { - CDebugDump dd; - dd.Open(pDebugDumpDir); - dd.Delete(); - } - catch (CABRTException& e) - { - /* Ignoring "directory already deleted" and such */ - } -} |
