diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-21 02:56:53 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-21 02:56:53 +0100 |
commit | 6443695f275167adb123070daf2a6b6ecc0bb371 (patch) | |
tree | e55e9cb7795f3a5fb239793eab60f2320fe11cbc /src | |
parent | f1322558475277ffed7a9c61f4b9478b4dd1d46c (diff) | |
download | abrt-6443695f275167adb123070daf2a6b6ecc0bb371.tar.gz abrt-6443695f275167adb123070daf2a6b6ecc0bb371.tar.xz abrt-6443695f275167adb123070daf2a6b6ecc0bb371.zip |
abrtd: fix Report() dbus call gaping security holes
We were blindly trusting the values passed to us
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/CLI/CLI.cpp | 8 | ||||
-rw-r--r-- | src/CLI/report.cpp | 12 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerDBus.cpp | 7 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerSocket.cpp | 3 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.cpp | 13 | ||||
-rw-r--r-- | src/Daemon/CrashWatcher.h | 2 | ||||
-rw-r--r-- | src/Daemon/Daemon.cpp | 12 | ||||
-rw-r--r-- | src/Daemon/MiddleWare.cpp | 231 | ||||
-rw-r--r-- | src/Gui/CCDump.py | 61 | ||||
-rw-r--r-- | src/Gui/CCReporterDialog.py | 154 |
10 files changed, 250 insertions, 253 deletions
diff --git a/src/CLI/CLI.cpp b/src/CLI/CLI.cpp index 5b96d7cb..a8786e99 100644 --- a/src/CLI/CLI.cpp +++ b/src/CLI/CLI.cpp @@ -55,7 +55,7 @@ static void print_crash_infos(vector_map_crash_data_t& pCrashInfos, int pMode) map_crash_data_t& info = pCrashInfos[ii]; if (pMode == OPT_GET_LIST_FULL || get_crash_data_item_content(info, CD_REPORTED) != "1") { - const char *timestr = get_crash_data_item_content(info, CD_TIME).c_str(); + const char *timestr = get_crash_data_item_content(info, FILENAME_TIME).c_str(); long time = strtol(timestr, NULL, 10); if (time == 0) error_msg_and_die("Error while converting time string."); @@ -73,10 +73,10 @@ static void print_crash_infos(vector_map_crash_data_t& pCrashInfos, int pMode) "\tCrash Time : %s\n" "\tCrash Count: %s\n"), ii, - get_crash_data_item_content(info, CD_UID).c_str(), + get_crash_data_item_content(info, FILENAME_UID).c_str(), get_crash_data_item_content(info, CD_UUID).c_str(), - get_crash_data_item_content(info, CD_PACKAGE).c_str(), - get_crash_data_item_content(info, CD_EXECUTABLE).c_str(), + get_crash_data_item_content(info, FILENAME_PACKAGE).c_str(), + get_crash_data_item_content(info, FILENAME_EXECUTABLE).c_str(), timeloc, get_crash_data_item_content(info, CD_COUNT).c_str() ); diff --git a/src/CLI/report.cpp b/src/CLI/report.cpp index 11037ca7..76cd3d5a 100644 --- a/src/CLI/report.cpp +++ b/src/CLI/report.cpp @@ -192,13 +192,13 @@ static void write_crash_report(const map_crash_data_t &report, FILE *fp) fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); - write_crash_report_field(fp, report, CD_COMMENT, + write_crash_report_field(fp, report, FILENAME_COMMENT, _("# Describe the circumstances of this crash below.")); - write_crash_report_field(fp, report, CD_REPRODUCE, + write_crash_report_field(fp, report, FILENAME_REPRODUCE, _("# How to reproduce the crash?")); write_crash_report_field(fp, report, FILENAME_BACKTRACE, _("# Stack trace: a list of active stack frames at the time the crash occurred\n# Check that it does not contain any sensitive data such as passwords.")); - write_crash_report_field(fp, report, CD_UUID, _("# UUID")); + write_crash_report_field(fp, report, CD_DUPHASH, "# DUPHASH"); write_crash_report_field(fp, report, FILENAME_ARCHITECTURE, _("# Architecture")); write_crash_report_field(fp, report, FILENAME_CMDLINE, _("# Command line")); write_crash_report_field(fp, report, FILENAME_COMPONENT, _("# Component")); @@ -282,10 +282,10 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, static int read_crash_report(map_crash_data_t &report, const char *text) { int result = 0; - result |= read_crash_report_field(text, report, CD_COMMENT); - result |= read_crash_report_field(text, report, CD_REPRODUCE); + result |= read_crash_report_field(text, report, FILENAME_COMMENT); + result |= read_crash_report_field(text, report, FILENAME_REPRODUCE); result |= read_crash_report_field(text, report, FILENAME_BACKTRACE); - result |= read_crash_report_field(text, report, CD_UUID); + result |= read_crash_report_field(text, report, CD_DUPHASH); result |= read_crash_report_field(text, report, FILENAME_ARCHITECTURE); result |= read_crash_report_field(text, report, FILENAME_CMDLINE); result |= read_crash_report_field(text, report, FILENAME_COMPONENT); diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index ddfbba49..f1f10e50 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -190,7 +190,8 @@ static int handle_CreateReport(DBusMessage* call, DBusMessage* reply) } long unix_uid = get_remote_uid(call); - map_crash_data_t report = CreateReport(pUUID, to_string(unix_uid).c_str(), /*force:*/ 0); + map_crash_data_t report; + CreateReport(pUUID, to_string(unix_uid).c_str(), /*force:*/ 0, report); DBusMessageIter out_iter; dbus_message_iter_init_append(reply, &out_iter); @@ -214,9 +215,9 @@ static int handle_Report(DBusMessage* call, DBusMessage* reply) return -1; } - map_crash_data_t::const_iterator it_comment = argin1.find(CD_COMMENT); + map_crash_data_t::const_iterator it_comment = argin1.find(FILENAME_COMMENT); const char* comment = (it_comment != argin1.end()) ? it_comment->second[CD_CONTENT].c_str() : ""; - map_crash_data_t::const_iterator it_reproduce = argin1.find(CD_REPRODUCE); + map_crash_data_t::const_iterator it_reproduce = argin1.find(FILENAME_REPRODUCE); const char* reproduce = (it_reproduce != argin1.end()) ? it_reproduce->second[CD_CONTENT].c_str() : ""; const char* errmsg = NULL; if (strlen(comment) > LIMIT_MESSAGE) diff --git a/src/Daemon/CommLayerServerSocket.cpp b/src/Daemon/CommLayerServerSocket.cpp index b54f9a6e..ab880fb2 100644 --- a/src/Daemon/CommLayerServerSocket.cpp +++ b/src/Daemon/CommLayerServerSocket.cpp @@ -145,7 +145,8 @@ void CCommLayerServerSocket::ProcessMessage(const std::string& pMessage, GIOChan else if (!strncmp(pMessage.c_str(), MESSAGE_CREATE_REPORT, sizeof(MESSAGE_CREATE_REPORT) - 1)) { // std::string UUID = pMessage.substr(sizeof(MESSAGE_CREATE_REPORT) - 1); -// map_crash_data_t crashReport = CreateReport(UUID, UID); +// map_crash_data_t crashReport; +// CreateReport(UUID, UID, crashReport); //use CreateReportThread instead of CreateReport? // std::string message = MESSAGE_CREATE_REPORT + crash_report_to_string(crashReport); // Send(message, pSource); diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp index 80d8cd47..93365f3b 100644 --- a/src/Daemon/CrashWatcher.cpp +++ b/src/Daemon/CrashWatcher.cpp @@ -57,12 +57,11 @@ vector_map_crash_data_t GetCrashInfos(const char *pUID) unsigned int ii; for (ii = 0; ii < UUIDsUIDs.size(); ii++) { - mw_result_t res; - map_crash_data_t info; const char *uuid = UUIDsUIDs[ii].first.c_str(); const char *uid = UUIDsUIDs[ii].second.c_str(); - res = FillCrashInfo(uuid, uid, info); + map_crash_data_t info; + mw_result_t res = FillCrashInfo(uuid, uid, info); switch (res) { case MW_OK: @@ -96,18 +95,18 @@ vector_map_crash_data_t GetCrashInfos(const char *pUID) * StartJob dbus call already did all the processing, and we just retrieve * the result from dump directory, which is fast. */ -map_crash_data_t CreateReport(const char* pUUID, const char* pUID, int force) +void CreateReport(const char* pUUID, const char* pUID, int force, map_crash_data_t& crashReport) { /* FIXME: starting from here, any shared data must be protected with a mutex. * For example, CreateCrashReport does: * g_pPluginManager->GetDatabase(g_settings_sDatabase.c_str()); * which is unsafe wrt concurrent updates to g_pPluginManager state. */ - map_crash_data_t crashReport; mw_result_t res = CreateCrashReport(pUUID, pUID, force, crashReport); switch (res) { case MW_OK: + VERB2 log_map_crash_data(crashReport, "crashReport"); break; case MW_IN_DB_ERROR: error_msg("Can't find crash with UUID %s in database", pUUID); @@ -120,7 +119,6 @@ map_crash_data_t CreateReport(const char* pUUID, const char* pUID, int force) DeleteDebugDump(pUUID, pUID); break; } - return crashReport; } typedef struct thread_data_t { @@ -140,7 +138,8 @@ static void* create_report(void* arg) try { log("Creating report..."); - map_crash_data_t crashReport = CreateReport(thread_data->UUID, thread_data->UID, thread_data->force); + map_crash_data_t crashReport; + CreateReport(thread_data->UUID, thread_data->UID, thread_data->force, crashReport); g_pCommLayer->JobDone(thread_data->peer, thread_data->UUID); } catch (CABRTException& e) diff --git a/src/Daemon/CrashWatcher.h b/src/Daemon/CrashWatcher.h index 1e672b96..31b72e08 100644 --- a/src/Daemon/CrashWatcher.h +++ b/src/Daemon/CrashWatcher.h @@ -50,7 +50,7 @@ class CCrashWatcher vector_map_crash_data_t GetCrashInfos(const char *pUID); int CreateReportThread(const char* pUUID, const char* pUID, int force, const char* pSender); -map_crash_data_t CreateReport(const char* pUUID, const char* pUID, int force); +void CreateReport(const char* pUUID, const char* pUID, int force, map_crash_data_t&); int DeleteDebugDump(const char *pUUID, const char *pUID); void DeleteDebugDump_by_dir(const char *dump_dir); diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 829b2a76..83b1ceef 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -328,7 +328,7 @@ static void FindNewDumps(const char* pPath) { case MW_OK: VERB1 log("Saving %s into database", itt->c_str()); - RunActionsAndReporters(get_crash_data_item_content(crashinfo, CD_MWDDD).c_str()); + RunActionsAndReporters(get_crash_data_item_content(crashinfo, CD_DUMPDIR).c_str()); break; case MW_IN_DB: VERB1 log("%s is already saved in database", itt->c_str()); @@ -479,14 +479,14 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin try { std::string fullname = concat_path_file(DEBUG_DUMPS_DIR, name); - map_crash_data_t crashinfo; //todo: rename SaveDebugDump to ???? it does not save crashinfo, it FETCHES crashinfo + map_crash_data_t crashinfo; mw_result_t res = SaveDebugDump(fullname.c_str(), crashinfo); switch (res) { case MW_OK: log("New crash, saving"); - RunActionsAndReporters(get_crash_data_item_content(crashinfo, CD_MWDDD).c_str()); + RunActionsAndReporters(get_crash_data_item_content(crashinfo, CD_DUMPDIR).c_str()); /* Fall through */ case MW_REPORTED: case MW_OCCURED: @@ -494,8 +494,8 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin if (res != MW_OK) log("Already saved crash, just sending dbus signal"); - const char *analyzer = get_crash_data_item_content(crashinfo, CD_MWANALYZER).c_str(); - const char *uid_str = get_crash_data_item_content(crashinfo, CD_UID).c_str(); + const char *analyzer = get_crash_data_item_content(crashinfo, FILENAME_ANALYZER).c_str(); + const char *uid_str = get_crash_data_item_content(crashinfo, FILENAME_UID).c_str(); /* Autoreport it if configured to do so */ if (analyzer_has_AutoReportUIDs(analyzer, uid_str)) @@ -525,7 +525,7 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin /* Send dbus signal */ if (analyzer_has_InformAllUsers(analyzer)) uid_str = NULL; - g_pCommLayer->Crash(get_crash_data_item_content(crashinfo, CD_PACKAGE).c_str(), uid_str); + g_pCommLayer->Crash(get_crash_data_item_content(crashinfo, FILENAME_PACKAGE).c_str(), uid_str); break; } case MW_BLACKLISTED: diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 9ca492de..ecf3c13a 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -148,37 +148,12 @@ static void load_crash_data_from_debug_dump(CDebugDump& dd, map_crash_data_t& da dd.LoadText(short_name.c_str(), content); free(text); - if (short_name == FILENAME_ARCHITECTURE - || short_name == FILENAME_KERNEL - || short_name == FILENAME_PACKAGE - || short_name == FILENAME_COMPONENT - || short_name == FILENAME_RELEASE - || short_name == FILENAME_EXECUTABLE - ) { - add_to_crash_data_ext(data, - short_name.c_str(), - CD_TXT, - CD_ISNOTEDITABLE, - content.c_str() - ); - continue; - } - - if (short_name != FILENAME_UID - && short_name != FILENAME_ANALYZER - && short_name != FILENAME_TIME - && short_name != FILENAME_DESCRIPTION - && short_name != FILENAME_REPRODUCE - && short_name != FILENAME_COMMENT - ) { - add_to_crash_data_ext( - data, - short_name.c_str(), - CD_TXT, - CD_ISEDITABLE, - content.c_str() - ); - } + add_to_crash_data_ext(data, + short_name.c_str(), + CD_TXT, + is_editable_file(short_name.c_str()) ? CD_ISEDITABLE : CD_ISNOTEDITABLE, + content.c_str() + ); } } @@ -190,16 +165,19 @@ static void load_crash_data_from_debug_dump(CDebugDump& dd, map_crash_data_t& da */ static void DebugDumpToCrashReport(const char *pDebugDumpDir, map_crash_data_t& pCrashData) { + VERB3 log(" DebugDumpToCrashReport('%s')", pDebugDumpDir); + CDebugDump dd; dd.Open(pDebugDumpDir); - if (!dd.Exist(FILENAME_ARCHITECTURE) - || !dd.Exist(FILENAME_KERNEL) - || !dd.Exist(FILENAME_PACKAGE) - || !dd.Exist(FILENAME_COMPONENT) - || !dd.Exist(FILENAME_RELEASE) - || !dd.Exist(FILENAME_EXECUTABLE) - ) { - throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): One or more of important file(s) are missing"); + + const char *const *v = must_have_files; + while (*v) + { + if (!dd.Exist(*v)) + { + throw CABRTException(EXCEP_ERROR, "DebugDumpToCrashReport(): important file '%s' is missing", *v); + } + v++; } load_crash_data_from_debug_dump(dd, pCrashData); @@ -245,7 +223,7 @@ static std::string GetGlobalUUID(const char *pAnalyzer, * @param pAnalyzer A name of an analyzer plugin. * @param pDebugDumpPath A debugdump dir containing all necessary data. */ -static void CreateReport(const char *pAnalyzer, +static void run_analyser_CreateReport(const char *pAnalyzer, const char *pDebugDumpDir, int force) { @@ -278,6 +256,7 @@ mw_result_t CreateCrashReport(const char *pUUID, return MW_IN_DB_ERROR; } + mw_result_t r = MW_OK; try { CDebugDump dd; @@ -296,45 +275,42 @@ mw_result_t CreateCrashReport(const char *pUUID, { dd.LoadText(FILENAME_REPRODUCE, reproduce); } + load_crash_data_from_debug_dump(dd, pCrashData); dd.Close(); VERB3 log(" CreateReport('%s')", analyzer.c_str()); - CreateReport(analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force); + run_analyser_CreateReport(analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force); std::string gUUID = GetGlobalUUID(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); VERB3 log(" GetGlobalUUID:'%s'", gUUID.c_str()); VERB3 log(" RunAnalyzerActions('%s','%s')", analyzer.c_str(), row.m_sDebugDumpDir.c_str()); RunAnalyzerActions(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); - VERB3 log(" DebugDumpToCrashReport"); DebugDumpToCrashReport(row.m_sDebugDumpDir.c_str(), pCrashData); - add_to_crash_data_ext(pCrashData, CD_UUID , CD_TXT, CD_ISNOTEDITABLE, gUUID.c_str() ); - add_to_crash_data_ext(pCrashData, CD_MWANALYZER, CD_SYS, CD_ISNOTEDITABLE, analyzer.c_str() ); - add_to_crash_data_ext(pCrashData, CD_MWUID , CD_SYS, CD_ISNOTEDITABLE, pUID ); - add_to_crash_data_ext(pCrashData, CD_MWUUID , CD_SYS, CD_ISNOTEDITABLE, pUUID ); - add_to_crash_data_ext(pCrashData, CD_COMMENT , CD_TXT, CD_ISEDITABLE , comment.c_str() ); - add_to_crash_data_ext(pCrashData, CD_REPRODUCE , CD_TXT, CD_ISEDITABLE , reproduce.c_str()); + add_to_crash_data_ext(pCrashData, CD_DUPHASH, CD_TXT, CD_ISNOTEDITABLE, gUUID.c_str()); + add_to_crash_data_ext(pCrashData, CD_UUID , CD_SYS, CD_ISNOTEDITABLE, pUUID); } catch (CABRTException& e) { + r = MW_CORRUPTED; error_msg("%s", e.what()); if (e.type() == EXCEP_DD_OPEN) { - return MW_ERROR; + r = MW_ERROR; } - if (e.type() == EXCEP_DD_LOAD) + else if (e.type() == EXCEP_DD_LOAD) { - return MW_FILE_ERROR; + r = MW_FILE_ERROR; } - if (e.type() == EXCEP_PLUGIN) + else if (e.type() == EXCEP_PLUGIN) { - return MW_PLUGIN_ERROR; + r = MW_PLUGIN_ERROR; } - return MW_CORRUPTED; } - return MW_OK; + VERB3 log("CreateCrashReport() returns %d", r); + return r; } void RunAction(const char *pActionDir, @@ -391,88 +367,74 @@ void RunActionsAndReporters(const char *pDebugDumpDir) } -static bool CheckReport(const map_crash_data_t& pCrashData) -{ - map_crash_data_t::const_iterator it_analyzer = pCrashData.find(CD_MWANALYZER); - map_crash_data_t::const_iterator it_mwuid = pCrashData.find(CD_MWUID); - map_crash_data_t::const_iterator it_mwuuid = pCrashData.find(CD_MWUUID); - - map_crash_data_t::const_iterator it_package = pCrashData.find(FILENAME_PACKAGE); - map_crash_data_t::const_iterator it_architecture = pCrashData.find(FILENAME_ARCHITECTURE); - map_crash_data_t::const_iterator it_kernel = pCrashData.find(FILENAME_KERNEL); - map_crash_data_t::const_iterator it_component = pCrashData.find(FILENAME_COMPONENT); - map_crash_data_t::const_iterator it_release = pCrashData.find(FILENAME_RELEASE); - map_crash_data_t::const_iterator it_executable = pCrashData.find(FILENAME_EXECUTABLE); - - map_crash_data_t::const_iterator end = pCrashData.end(); - - if (it_package == end) - { - return false; - } - - // FIXME: bypass the test if it's kerneloops - if (it_package->second[CD_CONTENT] == "kernel") - return true; - - if (it_analyzer == end || it_mwuid == end || - it_mwuuid == end || /* it_package == end || */ - it_architecture == end || it_kernel == end || - it_component == end || it_release == end || - it_executable == end) - { - return false; - } - - if (it_analyzer->second[CD_CONTENT] == "" || it_mwuid->second[CD_CONTENT] == "" || - it_mwuuid->second[CD_CONTENT] == "" || it_package->second[CD_CONTENT] == "" || - it_architecture->second[CD_CONTENT] == "" || it_kernel->second[CD_CONTENT] == "" || - it_component->second[CD_CONTENT] == "" || it_release->second[CD_CONTENT] == "" || - it_executable->second[CD_CONTENT] == "") - { - return false; - } - - return true; -} - -report_status_t Report(const map_crash_data_t& pCrashData, +// We must not trust client_report here! +// dbus handler passes it from user without checking +report_status_t Report(const map_crash_data_t& client_report, map_map_string_t& pSettings, const char *pUID) { - report_status_t ret; - - /* dbus handler passes pCrashData from user without checking it */ + map_crash_data_t::const_iterator itc_end = client_report.end(); - if (!CheckReport(pCrashData)) - { - throw CABRTException(EXCEP_ERROR, "Report(): Some of mandatory report data are missing."); + // Get ID fields + map_crash_data_t::const_iterator itc_UID = client_report.find(FILENAME_UID); + map_crash_data_t::const_iterator itc_UUID = client_report.find(CD_UUID); + if (itc_UID == itc_end /* || !exists itc_UID->second[CD_CONTENT] (TODO) */ + || itc_UUID == itc_end + ) { + throw CABRTException(EXCEP_ERROR, "Report(): UID or UUID is missing in client's report data"); } - const std::string& analyzer = get_crash_data_item_content(pCrashData, CD_MWANALYZER); - const std::string& UID = get_crash_data_item_content(pCrashData, CD_MWUID); - const std::string& UUID = get_crash_data_item_content(pCrashData, CD_MWUUID); - const std::string& packageNVR = get_crash_data_item_content(pCrashData, FILENAME_PACKAGE); - std::string packageName = packageNVR.substr(0, packageNVR.rfind("-", packageNVR.rfind("-") - 1)); + // Retrieve corresponding stored record + std::string UID = itc_UID->second[CD_CONTENT]; + std::string UUID = itc_UUID->second[CD_CONTENT]; + + map_crash_data_t stored_report; + mw_result_t r = FillCrashInfo(UUID.c_str(), UID.c_str(), stored_report); + if (r != MW_OK) + return report_status_t(); + const std::string& pDumpDir = get_crash_data_item_content(stored_report, CD_DUMPDIR); // Save comment and "how to reproduce" - map_crash_data_t::const_iterator it_comment = pCrashData.find(CD_COMMENT); - map_crash_data_t::const_iterator it_reproduce = pCrashData.find(CD_REPRODUCE); - if (it_comment != pCrashData.end() || it_reproduce != pCrashData.end()) + map_crash_data_t::const_iterator itc_COMMENT = client_report.find(FILENAME_COMMENT); + map_crash_data_t::const_iterator itc_REPRODUCE = client_report.find(FILENAME_REPRODUCE); + if (itc_COMMENT != itc_end || itc_REPRODUCE != itc_end) { - std::string pDumpDir = getDebugDumpDir(UUID.c_str(), UID.c_str()); CDebugDump dd; dd.Open(pDumpDir.c_str()); - if (it_comment != pCrashData.end()) + if (itc_COMMENT != itc_end && itc_COMMENT->second.size() > CD_CONTENT) { - dd.SaveText(FILENAME_COMMENT, it_comment->second[CD_CONTENT].c_str()); + const char *comment = itc_COMMENT->second[CD_CONTENT].c_str(); + dd.SaveText(FILENAME_COMMENT, comment); + add_to_crash_data_ext(stored_report, FILENAME_COMMENT, CD_TXT, CD_ISEDITABLE, comment); } - if (it_reproduce != pCrashData.end()) + if (itc_REPRODUCE != itc_end && itc_REPRODUCE->second.size() > CD_CONTENT) { - dd.SaveText(FILENAME_REPRODUCE, it_reproduce->second[CD_CONTENT].c_str()); + const char *reproduce = itc_REPRODUCE->second[CD_CONTENT].c_str(); + dd.SaveText(FILENAME_REPRODUCE, reproduce); + add_to_crash_data_ext(stored_report, FILENAME_REPRODUCE, CD_TXT, CD_ISEDITABLE, reproduce); } } + map_crash_data_t::const_iterator its_ANALYZER = stored_report.find(FILENAME_ANALYZER); + std::string analyzer = its_ANALYZER->second[CD_CONTENT]; + + std::string gUUID = GetGlobalUUID(analyzer.c_str(), pDumpDir.c_str()); + VERB3 log(" GetGlobalUUID:'%s'", gUUID.c_str()); + add_to_crash_data_ext(stored_report, CD_DUPHASH, CD_TXT, CD_ISNOTEDITABLE, gUUID.c_str()); + + // Run reporters + + VERB3 { + log("Run reporters"); + log_map_crash_data(client_report, " client_report"); + log_map_crash_data(stored_report, " stored_report"); + } +#define client_report client_report_must_not_be_used_below + + map_crash_data_t::const_iterator its_PACKAGE = stored_report.find(FILENAME_PACKAGE); + std::string packageNVR = its_PACKAGE->second[CD_CONTENT]; + std::string packageName = packageNVR.substr(0, packageNVR.rfind("-", packageNVR.rfind("-") - 1)); + // analyzer with package name (CCpp:xorg-x11-app) has higher priority std::string key = analyzer + ":" + packageName; map_analyzer_actions_and_reporters_t::iterator end = s_mapAnalyzerActionsAndReporters.end(); @@ -484,6 +446,7 @@ report_status_t Report(const map_crash_data_t& pCrashData, key = analyzer; } + report_status_t ret; std::string message; if (keyPtr != end) { @@ -518,7 +481,7 @@ report_status_t Report(const map_crash_data_t& pCrashData, } #endif map_plugin_settings_t plugin_settings = pSettings[plugin_name]; - std::string res = reporter->Report(pCrashData, plugin_settings, it_r->second.c_str()); + std::string res = reporter->Report(stored_report, plugin_settings, it_r->second.c_str()); #if 0 /* Using ~user/.abrt/ is bad wrt security */ if (home != "") @@ -548,6 +511,7 @@ report_status_t Report(const map_crash_data_t& pCrashData, database->DisConnect(); return ret; +#undef client_report } /** @@ -935,10 +899,7 @@ mw_result_t FillCrashInfo(const char *pUUID, { CDebugDump dd; dd.Open(row.m_sDebugDumpDir.c_str()); - dd.LoadText(FILENAME_EXECUTABLE, executable); - dd.LoadText(FILENAME_PACKAGE, package); - dd.LoadText(FILENAME_DESCRIPTION, description); - dd.LoadText(FILENAME_ANALYZER, analyzer); + load_crash_data_from_debug_dump(dd, pCrashData); } catch (CABRTException& e) { @@ -946,18 +907,14 @@ mw_result_t FillCrashInfo(const char *pUUID, return MW_ERROR; } - pCrashData.clear(); - add_to_crash_data(pCrashData, CD_EXECUTABLE , executable.c_str() ); - add_to_crash_data(pCrashData, CD_PACKAGE , package.c_str() ); - add_to_crash_data(pCrashData, CD_DESCRIPTION, description.c_str() ); - add_to_crash_data(pCrashData, CD_UUID , row.m_sUUID.c_str() ); - add_to_crash_data(pCrashData, CD_UID , row.m_sUID.c_str() ); - add_to_crash_data(pCrashData, CD_COUNT , row.m_sCount.c_str() ); - add_to_crash_data(pCrashData, CD_TIME , row.m_sTime.c_str() ); - add_to_crash_data(pCrashData, CD_REPORTED , row.m_sReported.c_str() ); - add_to_crash_data(pCrashData, CD_MESSAGE , row.m_sMessage.c_str() ); - add_to_crash_data(pCrashData, CD_MWDDD , row.m_sDebugDumpDir.c_str()); - add_to_crash_data(pCrashData, CD_MWANALYZER , analyzer.c_str() ); + add_to_crash_data(pCrashData, CD_UUID , row.m_sUUID.c_str() ); + add_to_crash_data(pCrashData, CD_COUNT , row.m_sCount.c_str() ); + add_to_crash_data(pCrashData, CD_REPORTED , row.m_sReported.c_str() ); + add_to_crash_data(pCrashData, CD_MESSAGE , row.m_sMessage.c_str() ); + add_to_crash_data(pCrashData, CD_DUMPDIR , row.m_sDebugDumpDir.c_str()); +//TODO: why do we keep uid and time in DB and in dumpdir?! + add_to_crash_data(pCrashData, FILENAME_UID , row.m_sUID.c_str() ); + add_to_crash_data(pCrashData, FILENAME_TIME , row.m_sTime.c_str() ); return MW_OK; } diff --git a/src/Gui/CCDump.py b/src/Gui/CCDump.py index 96d036c4..1f290929 100644 --- a/src/Gui/CCDump.py +++ b/src/Gui/CCDump.py @@ -3,20 +3,55 @@ from datetime import datetime from abrt_utils import _, init_logging, log, log1, log2 +# Should match CrashTypes.h! CD_TYPE = 0 CD_EDITABLE = 1 CD_CONTENT = 2 +CD_SYS = "s" +CD_BIN = "b" +CD_TXT = "t" + +FILENAME_ARCHITECTURE = "architecture" +FILENAME_KERNEL = "kernel" +FILENAME_TIME = "time" +FILENAME_UID = "uid" +FILENAME_PACKAGE = "package" +FILENAME_COMPONENT = "component" +FILENAME_DESCRIPTION = "description" +FILENAME_ANALYZER = "analyzer" +FILENAME_RELEASE = "release" +FILENAME_EXECUTABLE = "executable" +FILENAME_REASON = "reason" +FILENAME_COMMENT = "comment" +FILENAME_REPRODUCE = "reproduce" +FILENAME_RATING = "rating" +FILENAME_CMDLINE = "cmdline" +FILENAME_COREDUMP = "coredump" +FILENAME_BACKTRACE = "backtrace" +FILENAME_MEMORYMAP = "memorymap" +FILENAME_KERNELOOPS = "kerneloops" + +CD_DUPHASH = "DUPHASH" +CD_UUID = "UUID" +CD_DUMPDIR = "DumpDir" +CD_COUNT = "Count" +CD_REPORTED = "Reported" +CD_MESSAGE = "Message" + +# FIXME - create method or smth that returns type|editable|content + + class Dump(): """Class for mapping the debug dump to python object""" def __init__(self): self.UUID = None - self.UID = None + self.uid = None self.Count = None - self.Executable = None - self.Package = None - self.Time = None - self.Description = None + self.executable = None + self.package = None + self.time = None + self.description = None self.Message = None self.Reported = None @@ -24,16 +59,16 @@ class Dump(): return self.UUID[CD_CONTENT] def getUID(self): - return self.UID[CD_CONTENT] + return self.uid[CD_CONTENT] def getCount(self): return self.Count[CD_CONTENT] def getExecutable(self): - return self.Executable[CD_CONTENT] + return self.executable[CD_CONTENT] def getPackage(self): - return self.Package[CD_CONTENT] + return self.package[CD_CONTENT] def isReported(self): return self.Reported[CD_CONTENT] == "1" @@ -44,17 +79,17 @@ class Dump(): #return self.Message[CD_CONTENT].split('\n') return self.Message[CD_CONTENT] - def getTime(self,format): + def getTime(self, format): #print format if format: try: - return datetime.fromtimestamp(int(self.Time[CD_CONTENT])).strftime(format) + return datetime.fromtimestamp(int(self.time[CD_CONTENT])).strftime(format) except Exception, e: print e - return int(self.Time[CD_CONTENT]) + return int(self.time[CD_CONTENT]) def getPackageName(self): - return self.Package[CD_CONTENT][:self.Package[CD_CONTENT].find("-")] + return self.package[CD_CONTENT][:self.package[CD_CONTENT].find("-")] def getDescription(self): - return self.Description[CD_CONTENT] + return self.description[CD_CONTENT] diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py index d24c0dd8..f46c180f 100644 --- a/src/Gui/CCReporterDialog.py +++ b/src/Gui/CCReporterDialog.py @@ -11,16 +11,10 @@ from ABRTPlugin import PluginInfo from PluginSettingsUI import PluginSettingsUI from PluginList import getPluginInfoList #from CCDumpList import getDumpList, DumpList +from CCDump import * # FILENAME_xxx, CD_xxx from abrt_utils import _, log, log1, log2 # FIXME - create method or smth that returns type|editable|content -CD_TYPE = 0 -CD_EDITABLE = 1 -CD_CONTENT = 2 - -CD_SYS = "s" -CD_BIN = "b" -CD_TXT = "t" # response REFRESH = -50 @@ -34,7 +28,7 @@ class ReporterDialog(): self.report = report #Set the Glade file # FIXME add to path - builderfile = "%s%sreport.glade" % (sys.path[0],"/") + builderfile = "%s/report.glade" % sys.path[0] self.builder = gtk.Builder() self.builder.add_from_file(builderfile) #Get the Main Window, and connect the "destroy" event @@ -47,21 +41,20 @@ class ReporterDialog(): # comment textview self.tvComment = self.builder.get_object("tvComment") self.tvComment.connect("focus-in-event", self.on_comment_focus_cb) - self.comment_changed = False + self.show_hint_comment = 1 # "how to reproduce" textview self.tevHowToReproduce = self.builder.get_object("tevHowToReproduce") - self.how_to_changed = False self.builder.get_object("fErrors").hide() self.builder.get_object("bLog").connect("clicked", self.show_log_cb, log) self.builder.get_object("cbSendBacktrace").connect("toggled", self.on_send_backtrace_toggled) self.allow_send() self.hydrate() - + def check_backtrace(self): print "checking backtrace" - + def warn_user(self, warnings): # FIXME: show in lError fErrors = self.builder.get_object("fErrors") @@ -74,12 +67,12 @@ class ReporterDialog(): warning_lbl = "* %s" % warning lErrors.set_label(warning_lbl) fErrors.show_all() - + def hide_warning(self): fErrors = self.builder.get_object("fErrors") lErrors = self.builder.get_object("lErrors") fErrors.hide() - + def allow_send(self): self.hide_warning() bSend = self.builder.get_object("bSend") @@ -87,7 +80,7 @@ class ReporterDialog(): send = True error_msgs = [] try: - rating = self.report["rating"] + rating = self.report[FILENAME_RATING] except: rating = None # active buttons acording to required fields @@ -98,29 +91,30 @@ class ReporterDialog(): # we have both SendBacktrace and rating if rating: try: - package = self.report["package"][CD_CONTENT] + package = self.report[FILENAME_PACKAGE][CD_CONTENT] # if we don't have package for some reason except: package = None # not usable report - if int(self.report["rating"][CD_CONTENT]) < 3: + if int(self.report[FILENAME_RATING][CD_CONTENT]) < 3: if package: error_msgs.append(_("Reporting disabled because the backtrace is unusable.\nPlease try to install debuginfo manually using command: <b>debuginfo-install %s</b> \nthen use Refresh button to regenerate the backtrace." % package[0:package.rfind('-',0,package.rfind('-'))])) else: error_msgs.append(_("The backtrace is unusable, you can't report this!")) # probably usable 3 - elif int(self.report["rating"][CD_CONTENT]) < 4: + elif int(self.report[FILENAME_RATING][CD_CONTENT]) < 4: error_msgs.append(_("The backtrace is incomplete, please make sure you provide good steps to reproduce.")) - + if error_msgs: self.warn_user(error_msgs) bSend.set_sensitive(send) - + def on_send_backtrace_toggled(self, toggle_button): self.allow_send() - + def show_log_cb(self, widget, log): show_log(log, parent=self.window) + # this callback is called when user press Cancel or Report button in Report dialog def on_response(self, dialog, response_id, daemon): # the button has been pressed (probably) @@ -136,9 +130,10 @@ class ReporterDialog(): model[path][3] = not model[path][3] def on_comment_focus_cb(self, widget, event): - if not self.comment_changed: + if self.show_hint_comment: + # clear "hint" text by supplying a fresh, empty TextBuffer widget.set_buffer(gtk.TextBuffer()) - self.comment_changed = True + self.show_hint_comment = 0 def on_config_plugin_clicked(self, button, plugin, image): ui = PluginSettingsUI(plugin, parent=self.window) @@ -204,66 +199,77 @@ class ReporterDialog(): if len(text) > label_widget.get_max_width_chars(): label_widget.set_tooltip_text(text) label_widget.set_text(text) - + def hydrate(self): self.editable = [] + self.old_comment = "" + self.old_how_to_reproduce = "" for item in self.report: - if item == "backtrace": + try: + log2("report[%s]:%s/%s/%s", item, self.report[item][0], self.report[item][1], self.report[item][2][0:20]) + except: + pass + + if item == FILENAME_BACKTRACE: buff = gtk.TextBuffer() tvBacktrace = self.builder.get_object("tvBacktrace") buff.set_text(self.report[item][CD_CONTENT]) tvBacktrace.set_buffer(buff) continue - if item == "Comment": - buff = gtk.TextBuffer() - comment = _("Brief description how to reproduce this or what you did...") + + if item == FILENAME_COMMENT: try: if self.report[item][CD_CONTENT]: - comment = self.report[item][CD_CONTENT] - self.comment_changed = True + self.old_comment = self.report[item][CD_CONTENT] except Exception, e: pass - - buff.set_text(comment) - - self.tvComment.set_buffer(buff) continue - if item == "How to reproduce": - buff = gtk.TextBuffer() - how_to_reproduce = _("") + + if item == FILENAME_REPRODUCE: try: if self.report[item][CD_CONTENT]: - how_to_reproduce = self.report[item][CD_CONTENT] - self.how_to_changed = True + self.old_how_to_reproduce = self.report[item][CD_CONTENT] except Exception, e: pass + continue - buff.set_text(how_to_reproduce) + if self.report[item][CD_TYPE] == CD_SYS: + continue - self.tevHowToReproduce.set_buffer(buff) + # item name 0| value 1| editable? 2| toggled? 3| visible?(attachment)4 + # FIXME: handle editable fields + if self.report[item][CD_TYPE] == CD_BIN: + self.builder.get_object("fAttachment").show() + vbAttachments = self.builder.get_object("vbAttachments") + toggle = gtk.CheckButton(self.report[item][CD_CONTENT]) + vbAttachments.pack_start(toggle) + # bind item to checkbox + toggle.item = item + toggle.show() continue - if self.report[item][CD_TYPE] != CD_SYS: - # item name 0| value 1| editable? 2| toggled? 3| visible?(attachment)4 - # FIXME: handle editable fields - if self.report[item][CD_TYPE] == CD_BIN: - self.builder.get_object("fAttachment").show() - vbAttachments = self.builder.get_object("vbAttachments") - toggle = gtk.CheckButton(self.report[item][CD_CONTENT]) - vbAttachments.pack_start(toggle) - # bind item to checkbox - toggle.item = item - toggle.show() - continue - item_label = self.builder.get_object("l%s" % item) - if item_label: - self.set_label(item_label, self.report[item][CD_CONTENT]) - else: - # no widget to show this item - # probably some new item need to adjust the GUI! - # FIXME: add some window+button to show all the info - # in raw form (smth like the old report dialog) - pass + # It must be CD_TXT field + item_label = self.builder.get_object("l%s" % item) + if item_label: + self.set_label(item_label, self.report[item][CD_CONTENT]) + else: + # no widget to show this item + # probably some new item need to adjust the GUI! + # FIXME: add some window+button to show all the info + # in raw form (smth like the old report dialog) + pass + #end for + + buff = gtk.TextBuffer() + self.show_hint_comment = (self.old_comment == "") + if self.show_hint_comment: + buff.set_text(_("Brief description how to reproduce this or what you did...")) + else: + buff.set_text(self.old_comment) + self.tvComment.set_buffer(buff) + buff = gtk.TextBuffer() + buff.set_text(self.old_how_to_reproduce) + self.tevHowToReproduce.set_buffer(buff) def dehydrate(self): # handle attachments @@ -271,23 +277,22 @@ class ReporterDialog(): for attachment in vbAttachments.get_children(): #print "%s file %s" % (["not sending","sending"][attachment.get_active()], attachment.get_label()) del self.report[attachment.item] - + # handle comment - if self.comment_changed: - buff = self.tvComment.get_buffer() - self.report["Comment"] = [CD_TXT, 'y', buff.get_text(buff.get_start_iter(),buff.get_end_iter())] - else: - del self.report["Comment"] + buff = self.tvComment.get_buffer() + text = buff.get_text(buff.get_start_iter(), buff.get_end_iter()) + if self.old_comment != text: + self.report[FILENAME_COMMENT] = [CD_TXT, 'y', text] # handle how to reproduce - if self.how_to_changed: - buff = self.tevHowToReproduce.get_buffer() - self.report["How to reproduce"] = [CD_TXT, 'y', buff.get_text(buff.get_start_iter(),buff.get_end_iter())] - else: - del self.report["How to reproduce"] + buff = self.tevHowToReproduce.get_buffer() + text = buff.get_text(buff.get_start_iter(), buff.get_end_iter()) + if self.old_how_to_reproduce != text: + self.report[FILENAME_REPRODUCE] = [CD_TXT, 'y', text] #handle backtrace tev_backtrace = self.builder.get_object("tvBacktrace") buff = tev_backtrace.get_buffer() - self.report["backtrace"] = [CD_TXT, 'y', buff.get_text(buff.get_start_iter(),buff.get_end_iter())] + text = buff.get_text(buff.get_start_iter(), buff.get_end_iter()) + self.report[FILENAME_BACKTRACE] = [CD_TXT, 'y', text] def check_report(self): # FIXME: check the report for passwords and some other potentially @@ -299,4 +304,3 @@ class ReporterDialog(): result = self.window.run() self.window.destroy() return (result, self.report) - |