From b94e437131d1f396e1a700e2a5664199af008cfd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 10 Jan 2010 18:05:54 +0100 Subject: replace plugin enabling via EnabledPlugins by par-plugin Enabled = yes/no Signed-off-by: Denys Vlasenko --- lib/Plugins/CCpp.conf | 1 + lib/Plugins/SQLite3.conf | 1 + src/Daemon/Daemon.cpp | 7 -- src/Daemon/MiddleWare.cpp | 39 +++++++--- src/Daemon/PluginManager.cpp | 179 +++++++++++++++++++++---------------------- src/Daemon/PluginManager.h | 16 +--- src/Daemon/Settings.cpp | 7 -- src/Daemon/Settings.h | 1 - src/Daemon/abrt.conf | 6 +- src/Daemon/abrt.conf.5 | 4 - 10 files changed, 123 insertions(+), 138 deletions(-) diff --git a/lib/Plugins/CCpp.conf b/lib/Plugins/CCpp.conf index dfdbec8..153efb9 100644 --- a/lib/Plugins/CCpp.conf +++ b/lib/Plugins/CCpp.conf @@ -1,4 +1,5 @@ # Configuration file for CCpp hook and plugin +Enabled = yes # If you also want to dump file named "core" # in crashed process' current dir, set to "yes" diff --git a/lib/Plugins/SQLite3.conf b/lib/Plugins/SQLite3.conf index 3773c8f..2053642 100644 --- a/lib/Plugins/SQLite3.conf +++ b/lib/Plugins/SQLite3.conf @@ -1,3 +1,4 @@ # Configuration file for database plugin SQLite3 + # DB path DBPath = /var/cache/abrt/abrt-db diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 1a6cadf..7577611 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -173,13 +173,6 @@ static int SetUpMW() { g_setBlackList.insert(*it_b); } - VERB1 log("Registering plugins"); - set_string_t::iterator it_p = g_settings_setEnabledPlugins.begin(); - for (; it_p != g_settings_setEnabledPlugins.end(); it_p++) - { - if (g_pPluginManager->RegisterPlugin(it_p->c_str()) != 0) - return -1; - } VERB1 log("Adding actions or reporters"); vector_pair_string_string_t::iterator it_ar = g_settings_vectorActionsAndReporters.begin(); for (; it_ar != g_settings_vectorActionsAndReporters.end(); it_ar++) diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 25fe253..3656060 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -204,7 +204,11 @@ static void DebugDumpToCrashReport(const char *pDebugDumpDir, map_crash_report_t static std::string GetLocalUUID(const char *pAnalyzer, const char *pDebugDumpDir) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); - return analyzer->GetLocalUUID(pDebugDumpDir); + if (analyzer) + { + return analyzer->GetLocalUUID(pDebugDumpDir); + } + throw CABRTException(EXCEP_PLUGIN, "Error running '%s'", pAnalyzer); } /** @@ -217,7 +221,11 @@ static std::string GetGlobalUUID(const char *pAnalyzer, const char *pDebugDumpDir) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); - return analyzer->GetGlobalUUID(pDebugDumpDir); + if (analyzer) + { + return analyzer->GetGlobalUUID(pDebugDumpDir); + } + throw CABRTException(EXCEP_PLUGIN, "Error running '%s'", pAnalyzer); } /** @@ -232,7 +240,11 @@ static void CreateReport(const char *pAnalyzer, int force) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); - analyzer->CreateReport(pDebugDumpDir, force); + if (analyzer) + { + analyzer->CreateReport(pDebugDumpDir, force); + } + /* else: GetAnalyzer() already complained, no need to handle it here */ } mw_result_t CreateCrashReport(const char *pUUID, @@ -320,9 +332,14 @@ void RunAction(const char *pActionDir, const char *pPluginName, const char *pPluginArgs) { + CAction* action = g_pPluginManager->GetAction(pPluginName); + if (!action) + { + /* GetAction() already complained */ + return; + } try { - CAction* action = g_pPluginManager->GetAction(pPluginName); action->Run(pActionDir, pPluginArgs); } catch (CABRTException& e) @@ -770,13 +787,17 @@ static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir) for (; it_a != analyzer->second.end(); it_a++) { const char *plugin_name = it_a->first.c_str(); + CAction* action = g_pPluginManager->GetAction(plugin_name, /*silent:*/ true); + if (!action) + { + /* GetAction() already complained if no such plugin. + * If plugin exists but isn't an Action, it's not an error. + */ + continue; + } try { - if (g_pPluginManager->GetPluginType(plugin_name) == ACTION) - { - CAction* action = g_pPluginManager->GetAction(plugin_name); - action->Run(pDebugDumpDir, it_a->second.c_str()); - } + action->Run(pDebugDumpDir, it_a->second.c_str()); } catch (CABRTException& e) { diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 663228b..4aef630 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -138,7 +138,7 @@ void CPluginManager::LoadPlugins() if (!ext || strcmp(ext + 1, PLUGINS_LIB_EXTENSION) != 0) continue; *ext = '\0'; - LoadPlugin(dent->d_name + sizeof(PLUGINS_LIB_PREFIX)-1); + LoadPlugin(dent->d_name + sizeof(PLUGINS_LIB_PREFIX)-1, /*enabled_only:*/ true); } closedir(dir); } @@ -153,16 +153,37 @@ void CPluginManager::UnLoadPlugins() } } -void CPluginManager::LoadPlugin(const char *pName) +CPlugin* CPluginManager::LoadPlugin(const char *pName, bool enabled_only) { - if (m_mapLoadedModules.find(pName) != m_mapLoadedModules.end()) + map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); + if (it_plugin != m_mapPlugins.end()) { - return; + return it_plugin->second; /* ok */ + } + + const char *conf_name = pName; + if (strncmp(pName, "Kerneloops", sizeof("Kerneloops")-1) == 0) + { + /* Kerneloops{,Scanner,Reporter} share the same .conf file */ + conf_name = "Kerneloops"; + } + map_plugin_settings_t pluginSettings; + std::string conf_fullname = ssprintf(PLUGINS_CONF_DIR"/%s."PLUGINS_CONF_EXTENSION, conf_name); + LoadPluginSettings(conf_fullname.c_str(), pluginSettings); + VERB3 log("Loaded %s.conf", conf_name); + + if (enabled_only) + { + map_plugin_settings_t::iterator it = pluginSettings.find("Enabled"); + if (it == pluginSettings.end() || !string_to_bool(it->second.c_str())) + { + VERB3 log("Plugin %s: 'Enabled' is not set, not loading it (yet)", pName); + return NULL; /* error */ + } } std::string libPath = ssprintf(PLUGINS_LIB_DIR"/"PLUGINS_LIB_PREFIX"%s."PLUGINS_LIB_EXTENSION, pName); CLoadedModule* module = new CLoadedModule(libPath.c_str()); - if (module->GetMagicNumber() != PLUGINS_MAGIC_NUMBER || module->GetType() < 0 || module->GetType() > MAX_PLUGIN_TYPE @@ -172,95 +193,63 @@ void CPluginManager::LoadPlugin(const char *pName) module->GetMagicNumber(), PLUGINS_MAGIC_NUMBER, module->GetType(), MAX_PLUGIN_TYPE); delete module; - return; - } - - log("Plugin %s (%s) succesfully loaded", pName, module->GetVersion()); - m_mapLoadedModules[pName] = module; -} - -void CPluginManager::UnLoadPlugin(const char *pName) -{ - map_loaded_module_t::iterator it_module = m_mapLoadedModules.find(pName); - if (it_module != m_mapLoadedModules.end()) - { - UnRegisterPlugin(pName); - delete it_module->second; - m_mapLoadedModules.erase(it_module); - log("Plugin %s successfully unloaded", pName); + return NULL; /* error */ } -} + VERB3 log("Loaded plugin %s v.%s", pName, module->GetVersion()); -int CPluginManager::RegisterPlugin(const char *pName) -{ - map_loaded_module_t::iterator it_module = m_mapLoadedModules.find(pName); - if (it_module == m_mapLoadedModules.end()) - { - error_msg("Can't initialize plugin %s: no such plugin installed", pName); - return -1; /* failure */ - } - if (m_mapPlugins.find(pName) != m_mapPlugins.end()) - { - return 0; /* already registered, success */ - } - - /* Loaded, but not registered yet */ - CPlugin* plugin = it_module->second->PluginNew(); - map_plugin_settings_t pluginSettings; - - const char *conf_name = pName; - if (strncmp(pName, "Kerneloops", sizeof("Kerneloops")-1) == 0) { - /* Kerneloops{,Scanner,Reporter} share the same .conf file */ - conf_name = "Kerneloops"; - } - LoadPluginSettings(ssprintf(PLUGINS_CONF_DIR"/%s."PLUGINS_CONF_EXTENSION, conf_name).c_str(), pluginSettings); - VERB3 log("Loaded %s.conf", conf_name); + CPlugin* plugin = NULL; try { + plugin = module->PluginNew(); plugin->Init(); plugin->SetSettings(pluginSettings); } catch (CABRTException& e) { - error_msg("Can't initialize plugin %s(%s): %s", + error_msg("Can't initialize plugin %s: %s", pName, - plugin_type_str[it_module->second->GetType()], e.what() ); - UnLoadPlugin(pName); - return -1; /* failure */ + delete plugin; + delete module; + return NULL; /* error */ } - m_mapPlugins[pName] = plugin; - log("Registered plugin %s(%s)", pName, plugin_type_str[it_module->second->GetType()]); - return 0; /* success */ -} -void CPluginManager::RegisterPluginDBUS(const char *pName, const char *pDBUSSender) -{ - int polkit_result = polkit_check_authorization(pDBUSSender, - "org.fedoraproject.abrt.change-daemon-settings"); - if (polkit_result == PolkitYes) - { - RegisterPlugin(pName); - } else - { - log("User %s not authorized, returned %d", pDBUSSender, polkit_result); - } + m_mapLoadedModules[pName] = module; + m_mapPlugins[pName] = plugin; + log("Registered %s plugin '%s'", plugin_type_str[module->GetType()], pName); + return plugin; /* ok */ } -void CPluginManager::UnRegisterPlugin(const char *pName) +void CPluginManager::UnLoadPlugin(const char *pName) { map_loaded_module_t::iterator it_module = m_mapLoadedModules.find(pName); if (it_module != m_mapLoadedModules.end()) { map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin != m_mapPlugins.end()) + if (it_plugin != m_mapPlugins.end()) /* always true */ { it_plugin->second->DeInit(); delete it_plugin->second; m_mapPlugins.erase(it_plugin); - log("UnRegistered plugin %s(%s)", pName, plugin_type_str[it_module->second->GetType()]); } + delete it_module->second; + m_mapLoadedModules.erase(it_module); + log("UnRegistered %s plugin %s", plugin_type_str[it_module->second->GetType()], pName); + } +} + +void CPluginManager::RegisterPluginDBUS(const char *pName, const char *pDBUSSender) +{ + int polkit_result = polkit_check_authorization(pDBUSSender, + "org.fedoraproject.abrt.change-daemon-settings"); + if (polkit_result == PolkitYes) + { +//TODO: report success/failure + LoadPlugin(pName); + } else + { + log("User %s not authorized, returned %d", pDBUSSender, polkit_result); } } @@ -270,7 +259,7 @@ void CPluginManager::UnRegisterPluginDBUS(const char *pName, const char *pDBUSSe "org.fedoraproject.abrt.change-daemon-settings"); if (polkit_result == PolkitYes) { - UnRegisterPlugin(pName); + UnLoadPlugin(pName); } else { log("user %s not authorized, returned %d", pDBUSSender, polkit_result); @@ -280,50 +269,57 @@ void CPluginManager::UnRegisterPluginDBUS(const char *pName, const char *pDBUSSe CAnalyzer* CPluginManager::GetAnalyzer(const char *pName) { - map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin == m_mapPlugins.end()) + CPlugin* plugin = LoadPlugin(pName); + if (!plugin) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName); + error_msg("Plugin '%s' is not registered", pName); + return NULL; } if (m_mapLoadedModules[pName]->GetType() != ANALYZER) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not an analyzer plugin", pName); + error_msg("Plugin '%s' is not an analyzer plugin", pName); + return NULL; } - return (CAnalyzer*)(it_plugin->second); + return (CAnalyzer*)plugin; } CReporter* CPluginManager::GetReporter(const char *pName) { - map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin == m_mapPlugins.end()) + CPlugin* plugin = LoadPlugin(pName); + if (!plugin) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName); + error_msg("Plugin '%s' is not registered", pName); + return NULL; } if (m_mapLoadedModules[pName]->GetType() != REPORTER) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not a reporter plugin", pName); + error_msg("Plugin '%s' is not a reporter plugin", pName); + return NULL; } - return (CReporter*)(it_plugin->second); + return (CReporter*)plugin; } -CAction* CPluginManager::GetAction(const char *pName) +CAction* CPluginManager::GetAction(const char *pName, bool silent) { - map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin == m_mapPlugins.end()) + CPlugin* plugin = LoadPlugin(pName); + if (!plugin) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName); + error_msg("Plugin '%s' is not registered", pName); + return NULL; } if (m_mapLoadedModules[pName]->GetType() != ACTION) { - throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not an action plugin", pName); + if (!silent) + error_msg("Plugin '%s' is not an action plugin", pName); + return NULL; } - return (CAction*)(it_plugin->second); + return (CAction*)plugin; } CDatabase* CPluginManager::GetDatabase(const char *pName) { - map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin == m_mapPlugins.end()) + CPlugin* plugin = LoadPlugin(pName); + if (!plugin) { throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName); } @@ -331,17 +327,18 @@ CDatabase* CPluginManager::GetDatabase(const char *pName) { throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not a database plugin", pName); } - return (CDatabase*)(it_plugin->second); + return (CDatabase*)plugin; } plugin_type_t CPluginManager::GetPluginType(const char *pName) { - map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); - if (it_plugin == m_mapPlugins.end()) + CPlugin* plugin = LoadPlugin(pName); + if (!plugin) { throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName); } - return m_mapLoadedModules[pName]->GetType(); + map_loaded_module_t::iterator it_module = m_mapLoadedModules.find(pName); + return it_module->second->GetType(); } vector_map_string_t CPluginManager::GetPluginsInfo() diff --git a/src/Daemon/PluginManager.h b/src/Daemon/PluginManager.h index 2d649c5..65058a5 100644 --- a/src/Daemon/PluginManager.h +++ b/src/Daemon/PluginManager.h @@ -74,7 +74,7 @@ class CPluginManager * A method, which loads particular plugin. * @param pName A plugin name. */ - void LoadPlugin(const char *pName); + CPlugin* LoadPlugin(const char *pName, bool enabled_only = false); /** * A method, which unloads particular plugin. * @param pName A plugin name. @@ -84,18 +84,6 @@ class CPluginManager * A method, which registers particular plugin. * @param pName A plugin name. */ - int RegisterPlugin(const char *pName); - /** - * A method, which unregister particular plugin. - * @param pName A plugin name. - */ - void UnRegisterPlugin(const char *pName); - /** - * A method, which registers particular plugin, - * called via DBUS - * @param pName A plugin name. - * @param pDBUSSender DBUS user identification - */ void RegisterPluginDBUS(const char *pName, const char *pDBUSSender); /** * A method, which unregister particular plugin, @@ -121,7 +109,7 @@ class CPluginManager * @param pName A plugin name. * @return An action plugin. */ - CAction* GetAction(const char *pName); + CAction* GetAction(const char *pName, bool silent = false); /** * A method, which returns instance of particular database plugin. * @param pName A plugin name. diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp index d89bebf..48658e2 100644 --- a/src/Daemon/Settings.cpp +++ b/src/Daemon/Settings.cpp @@ -37,7 +37,6 @@ bool g_settings_bOpenGPGCheck = false; /* one line: "OpenGPGPublicKeys = value1,value2" */ set_string_t g_settings_setOpenGPGPublicKeys; set_string_t g_settings_mapBlackList; -set_string_t g_settings_setEnabledPlugins; std::string g_settings_sDatabase; unsigned int g_settings_nMaxCrashReportsSize = 1000; /* one line: "ActionsAndReporters = aa_first,bb_first(bb_second),cc_first" */ @@ -168,11 +167,6 @@ static void ParseCommon() { g_settings_sDatabase = it->second; } - it = s_mapSectionCommon.find("EnabledPlugins"); - if (it != end) - { - g_settings_setEnabledPlugins = ParseList(it->second.c_str()); - } it = s_mapSectionCommon.find("MaxCrashReportsSize"); if (it != end) { @@ -434,7 +428,6 @@ void SaveSettings() SaveBool("OpenGPGCheck", g_settings_bOpenGPGCheck, fOut); SaveSetString("OpenGPGPublicKeys", g_settings_setOpenGPGPublicKeys, fOut); SaveSetString("BlackList", g_settings_mapBlackList, fOut); - SaveSetString("EnabledPlugins", g_settings_setEnabledPlugins, fOut); fprintf(fOut, "Database = %s\n", g_settings_sDatabase.c_str()); fprintf(fOut, "MaxCrashReportsSize = %u\n", g_settings_nMaxCrashReportsSize); SaveVectorPairStrings("ActionsAndReporters", g_settings_vectorActionsAndReporters, fOut); diff --git a/src/Daemon/Settings.h b/src/Daemon/Settings.h index 9ee9370..3fdb8b9 100644 --- a/src/Daemon/Settings.h +++ b/src/Daemon/Settings.h @@ -9,7 +9,6 @@ typedef map_map_string_t map_abrt_settings_t; extern set_string_t g_settings_setOpenGPGPublicKeys; extern set_string_t g_settings_mapBlackList; -extern set_string_t g_settings_setEnabledPlugins; extern unsigned int g_settings_nMaxCrashReportsSize; extern bool g_settings_bOpenGPGCheck; extern std::string g_settings_sDatabase; diff --git a/src/Daemon/abrt.conf b/src/Daemon/abrt.conf index 276bf25..acf8566 100644 --- a/src/Daemon/abrt.conf +++ b/src/Daemon/abrt.conf @@ -9,11 +9,7 @@ OpenGPGCheck = no OpenGPGPublicKeys = /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora # Blacklisted packages BlackList = nspluginwrapper -# Enabled plugins. -# You can disable handling e.g. Python crashes by not listing Python here. -# There has to be exactly one database plugin enabled. -EnabledPlugins = SQLite3, CCpp, Logger, Kerneloops, KerneloopsScanner, KerneloopsReporter, Bugzilla, Python, RunApp -# Database +# Which database plugin to use Database = SQLite3 # Max size for crash storage [MiB] MaxCrashReportsSize = 1000 diff --git a/src/Daemon/abrt.conf.5 b/src/Daemon/abrt.conf.5 index 3b172bc..7114f5c 100644 --- a/src/Daemon/abrt.conf.5 +++ b/src/Daemon/abrt.conf.5 @@ -30,10 +30,6 @@ to report them if "EnableOpenGPG = yes". .I abrt will ignore packages in this list and will not handle their crashes. .TP -.B EnabledPlugins = \fIplugin\fP, \fIplugin\fP ... -.I abrt -will only load plugins in this list. -.TP .B Database = \fIdatabasePlugin\fP This specifies which database plugin .I abrt -- cgit From d36042c8e3722cc34c95bee69bade25c55a234ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:17:11 +0100 Subject: SQLite3: check for SQL injection Signed-off-by: Denys Vlasenko --- lib/Plugins/SQLite3.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp index 1979f24..0963456 100644 --- a/lib/Plugins/SQLite3.cpp +++ b/lib/Plugins/SQLite3.cpp @@ -90,6 +90,26 @@ static const char *const upate_sql_commands[][ABRT_TABLE_VERSION + 1] = { }, }; + +/* Is this string safe wrt SQL injection? + * PHP's mysql_real_escape_string() treats \, ', ", \x00, \n, \r, and \x1a as special. + * We are a bit more paranoid and disallow any control chars. + */ +static bool is_string_safe(const char *str) +{ + const char *p = str; + while (*p) + { + if ((unsigned char)(*p) < ' ' || strchr("\\\"\'", *p)) + { + error_msg("Probable SQL injection: '%s'", str); + return false; + } + p++; + } + return true; +} + static void get_table(vector_database_rows_t& pTable, sqlite3 *db, const char *fmt, ...) { @@ -308,6 +328,14 @@ void CSQLite3::Insert_or_Update(const char *pUUID, const char *pDebugDumpPath, const char *pTime) { + if (!is_string_safe(pUUID) + || !is_string_safe(pUID) + || !is_string_safe(pDebugDumpPath) + || !is_string_safe(pTime) + ) { + return; + } + if (!exists_uuid_uid(m_pDB, pUUID, pUID)) { execute_sql(m_pDB, @@ -336,6 +364,12 @@ void CSQLite3::Insert_or_Update(const char *pUUID, void CSQLite3::DeleteRow(const char *pUUID, const char *pUID) { + if (!is_string_safe(pUUID) + || !is_string_safe(pUID) + ) { + return; + } + if (pUID[0] == '0' && !pUID[1]) { execute_sql(m_pDB, @@ -360,6 +394,11 @@ void CSQLite3::DeleteRow(const char *pUUID, const char *pUID) void CSQLite3::DeleteRows_by_dir(const char *dump_dir) { + if (!is_string_safe(dump_dir)) + { + return; + } + execute_sql(m_pDB, "DELETE FROM "ABRT_TABLE" " "WHERE "COL_DEBUG_DUMP_PATH" = '%s'", @@ -369,6 +408,13 @@ void CSQLite3::DeleteRows_by_dir(const char *dump_dir) void CSQLite3::SetReported(const char *pUUID, const char *pUID, const char *pMessage) { + if (!is_string_safe(pUUID) + || !is_string_safe(pUID) + || !is_string_safe(pMessage) + ) { + return; + } + if (pUID[0] == '0' && !pUID[1]) { execute_sql(m_pDB, @@ -409,6 +455,12 @@ void CSQLite3::SetReported(const char *pUUID, const char *pUID, const char *pMes vector_database_rows_t CSQLite3::GetUIDData(const char *pUID) { vector_database_rows_t table; + + if (!is_string_safe(pUID)) + { + return table; + } + if (pUID[0] == '0' && !pUID[1]) { get_table(table, m_pDB, "SELECT * FROM "ABRT_TABLE";"); @@ -426,6 +478,12 @@ vector_database_rows_t CSQLite3::GetUIDData(const char *pUID) database_row_t CSQLite3::GetRow(const char *pUUID, const char *pUID) { + if (!is_string_safe(pUUID) + || !is_string_safe(pUID) + ) { + return database_row_t(); + } + vector_database_rows_t table; if (pUID[0] == '0' && !pUID[1]) -- cgit From b0abdde8871b0366868b917df040a8880165ba30 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:17:54 +0100 Subject: DebugDump: use more restrictive modes Signed-off-by: Denys Vlasenko --- lib/Utils/DebugDump.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index b4c3ee4..86e198c 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -244,13 +244,18 @@ void CDebugDump::Create(const char *pDir, int64_t uid) Lock(); m_bOpened = true; - if (mkdir(m_sDebugDumpDir.c_str(), 0700) == -1) + /* Was creating it with mode 0700, 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(), 0500) == -1) { UnLock(); m_bOpened = false; throw CABRTException(EXCEP_DD_OPEN, "Can't create dir '%s'", pDir); } - if (chmod(m_sDebugDumpDir.c_str(), 0700) == -1) + /* paranoia? mkdir should have done it already */ + if (chmod(m_sDebugDumpDir.c_str(), 0500) == -1) { UnLock(); m_bOpened = false; @@ -361,7 +366,12 @@ static void LoadTextFile(const char *pPath, std::string& pData) static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize) { - int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666); + /* Was creating it with mode 0666, but this allows the user to replace + * file's contents, changing security-sensitive data + * (e.g. "uid", "analyzer", "executable") + */ + unlink(pPath); + int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0444); if (fd < 0) { throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s'", pPath); @@ -393,6 +403,7 @@ void CDebugDump::SaveText(const char* pName, const char* pData) std::string fullPath = concat_path_file(m_sDebugDumpDir.c_str(), pName); SaveBinaryFile(fullPath.c_str(), pData, strlen(pData)); } + void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize) { if (!m_bOpened) -- cgit From 658622eb5e1b81d394f066df44bc9f0abe9cc807 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:18:56 +0100 Subject: RunApp: safer chdir. Overhauled "sparn a child and get its output" in general Signed-off-by: Denys Vlasenko --- inc/abrtlib.h | 26 +++++++- lib/Plugins/CCpp.cpp | 70 +++++++-------------- lib/Plugins/RunApp.cpp | 32 +++------- lib/Plugins/SOSreport.cpp | 4 +- lib/Utils/Makefile.am | 2 +- lib/Utils/popen_and_save_output.cpp | 30 --------- lib/Utils/spawn.cpp | 121 ++++++++++++++++++++++++++++++++++++ lib/Utils/xfuncs.cpp | 6 ++ 8 files changed, 186 insertions(+), 105 deletions(-) delete mode 100644 lib/Utils/popen_and_save_output.cpp create mode 100644 lib/Utils/spawn.cpp diff --git a/inc/abrtlib.h b/inc/abrtlib.h index 28140d8..fadd7f1 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -132,6 +132,7 @@ int xsocket(int domain, int type, int protocol); void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); void xlisten(int s, int backlog); ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, socklen_t tolen); +void xchdir(const char *path); void xstat(const char *name, struct stat *stat_buf); /* Just testing dent->d_type == DT_REG is wrong: some filesystems * do not report the type, they report DT_UNKNOWN for every dirent @@ -161,6 +162,30 @@ off_t copy_file(const char *src_name, const char *dst_name); void xsetreuid(uid_t ruid, uid_t euid); void xsetregid(gid_t rgid, uid_t egid); +enum { + EXECFLG_INPUT = 1 << 0, + EXECFLG_OUTPUT = 1 << 1, + EXECFLG_INPUT_NUL = 1 << 2, + EXECFLG_OUTPUT_NUL = 1 << 3, + EXECFLG_ERR2OUT = 1 << 4, + EXECFLG_ERR_NUL = 1 << 5, + EXECFLG_QUIET = 1 << 6, + EXECFLG_SETGUID = 1 << 7, + EXECFLG_SETSID = 1 << 8, +}; +/* Returns pid */ +pid_t fork_execv_on_steroids(int flags, + char **argv, + int *pipefds, + char **unsetenv_vec, + const char *dir, + uid_t uid); +/* Returns malloc'ed string. NULs are retained, and extra one is appended + * after the last byte (this NUL is not accounted for in *size_p) */ +char *run_in_shell_and_save_output(int flags, + const char *cmd, + const char *dir, + size_t *size_p); unsigned long long monotonic_ns(void); @@ -246,7 +271,6 @@ to_string(T x) return o.str(); } -std::string popen_and_save_output(const char *cmd); void parse_args(const char *psArgs, vector_string_t& pArgs, int quote = -1); void parse_release(const char *pRelease, std::string& pProduct, std::string& pVersion); diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 1a01c01..26562be 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -99,54 +99,28 @@ static string concat_str_vector(char **strings) /* Returns status. See `man 2 wait` for status information. */ static int ExecVP(char **pArgs, uid_t uid, int redirect_stderr, string& pOutput) { - int pipeout[2]; - pid_t child; - - xpipe(pipeout); - child = fork(); - if (child == -1) - { - perror_msg_and_die("fork"); - } - if (child == 0) - { - VERB1 log("Executing: %s", concat_str_vector(pArgs).c_str()); - close(pipeout[0]); /* read side of the pipe */ - xmove_fd(pipeout[1], STDOUT_FILENO); - /* Make sure stdin is safely open to nothing */ - xmove_fd(xopen("/dev/null", O_RDONLY), STDIN_FILENO); - - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - setgroups(1, &gid); - xsetregid(gid, gid); - xsetreuid(uid, uid); - setsid(); - - /* Nuke everything which may make setlocale() switch to non-POSIX locale: - * we need to avoid having gdb output in some obscure language. - */ - unsetenv("LANG"); - unsetenv("LC_ALL"); - unsetenv("LC_COLLATE"); - unsetenv("LC_CTYPE"); - unsetenv("LC_MESSAGES"); - unsetenv("LC_MONETARY"); - unsetenv("LC_NUMERIC"); - unsetenv("LC_TIME"); - - if (redirect_stderr) - { - /* We want parent to see errors in the same stream */ - xdup2(STDOUT_FILENO, STDERR_FILENO); - } - execvp(pArgs[0], pArgs); - /* VERB1 since sometimes we expect errors here */ - VERB1 perror_msg("Can't execute '%s'", pArgs[0]); - exit(1); - } + /* Nuke everything which may make setlocale() switch to non-POSIX locale: + * we need to avoid having gdb output in some obscure language. + */ + static const char *const unsetenv_vec[] = { + "LANG", + "LC_ALL", + "LC_COLLATE", + "LC_CTYPE", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NUMERIC", + "LC_TIME", + NULL + }; + + int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID | EXECFLG_QUIET; + if (redirect_stderr) + flags |= EXECFLG_ERR2OUT; + VERB1 flags &= ~EXECFLG_QUIET; - close(pipeout[1]); /* write side of the pipe */ + int pipeout[2]; + pid_t child = fork_execv_on_steroids(flags, pArgs, pipeout, (char**)unsetenv_vec, /*dir:*/ NULL, uid); int r; char buff[1024]; @@ -155,8 +129,8 @@ static int ExecVP(char **pArgs, uid_t uid, int redirect_stderr, string& pOutput) buff[r] = '\0'; pOutput += buff; } - close(pipeout[0]); + int status; waitpid(child, &status, 0); /* prevent having zombie child process */ diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp index f7cbc01..c1f725b 100644 --- a/lib/Plugins/RunApp.cpp +++ b/lib/Plugins/RunApp.cpp @@ -33,7 +33,8 @@ using namespace std; void CActionRunApp::Run(const char *pActionDir, const char *pArgs) { - /* Don't update_client() - actions run at crash time */ + /* Don't update_client() - actions run at crash time, there is no client + * to talk to at that point */ log("RunApp('%s','%s')", pActionDir, pArgs); vector_string_t args; @@ -45,38 +46,21 @@ void CActionRunApp::Run(const char *pActionDir, const char *pArgs) return; } -//FIXME: need to be able to escape " in .conf - /* Chdir to the dump dir. Command can analyze component and such. + /* NB: we chdir to the dump dir. Command can analyze component and such. * Example: * test x"`cat component`" = x"xorg-x11-apps" && cp /var/log/Xorg.0.log . */ -//Can do it using chdir() in child if we'd open-code popen - string cd_and_cmd = ssprintf("cd '%s'; %s", pActionDir, cmd); - VERB1 log("RunApp: executing '%s'", cd_and_cmd.c_str()); - FILE *fp = popen(cd_and_cmd.c_str(), "r"); - if (fp == NULL) - { - /* Happens only on resource starvation (fork fails or out-of-mem) */ - return; - } - -//FIXME: RunApp("gzip -9 FILENAME) - output += line; - } - pclose(fp); + size_t cmd_out_size; + char *cmd_out = run_in_shell_and_save_output(/*flags:*/ 0, cmd, pActionDir, &cmd_out_size); if (args.size() > FILENAME) { CDebugDump dd; dd.Open(pActionDir); - dd.SaveText(args[FILENAME].c_str(), output.c_str()); + dd.SaveBinary(args[FILENAME].c_str(), cmd_out, cmd_out_size); } + + free(cmd_out); } PLUGIN_INFO(ACTION, diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp index 6f23165..899b446 100644 --- a/lib/Plugins/SOSreport.cpp +++ b/lib/Plugins/SOSreport.cpp @@ -91,7 +91,9 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) update_client(_("running sosreport: %s"), command.c_str()); std::string output = command; output += '\n'; - output += popen_and_save_output(command.c_str()); + char *command_out = run_in_shell_and_save_output(/*flags:*/ 0, command.c_str(), /*dir:*/ NULL, /*size_p:*/ NULL); + output += command_out; + free(command_out); update_client(_("done running sosreport")); std::string sosreport_filename = ParseFilename(output); diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am index d5e9d98..a944d97 100644 --- a/lib/Utils/Makefile.am +++ b/lib/Utils/Makefile.am @@ -16,7 +16,7 @@ libABRTUtils_la_SOURCES = \ daemon.cpp \ skip_whitespace.cpp \ xatonum.cpp \ - popen_and_save_output.cpp \ + spawn.cpp \ stringops.cpp \ dirsize.cpp \ DebugDump.h DebugDump.cpp \ diff --git a/lib/Utils/popen_and_save_output.cpp b/lib/Utils/popen_and_save_output.cpp deleted file mode 100644 index 4bcbcac..0000000 --- a/lib/Utils/popen_and_save_output.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Utility routines. - * - * Licensed under GPLv2 or later, see file COPYING in this tarball for details. - */ -#include "abrtlib.h" - -using namespace std; - -string popen_and_save_output(const char *cmd) -{ - string result; - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) /* fork or pipe failed; or out-of-mem */ - { - return result; - } - - size_t sz; - char buf[BUFSIZ + 1]; - while ((sz = fread(buf, 1, sizeof(buf)-1, fp)) > 0) - { - buf[sz] = '\0'; - result += buf; - } - pclose(fp); - - return result; -} diff --git a/lib/Utils/spawn.cpp b/lib/Utils/spawn.cpp new file mode 100644 index 0000000..4b0eecb --- /dev/null +++ b/lib/Utils/spawn.cpp @@ -0,0 +1,121 @@ +/* + * Utility routines. + * + * Licensed under GPLv2, see file COPYING in this tarball for details. + */ +#include "abrtlib.h" + +/* Returns pid */ +pid_t fork_execv_on_steroids(int flags, + char **argv, + int *pipefds, + char **unsetenv_vec, + const char *dir, + uid_t uid) +{ + pid_t child; + /* Reminder: [0] is read end, [1] is write end */ + int pipe_to_child[2]; + int pipe_fm_child[2]; + + /* Sanitize flags */ + if (!pipefds) + flags &= ~(EXECFLG_INPUT | EXECFLG_OUTPUT); + + if (flags & EXECFLG_INPUT) + xpipe(pipe_to_child); + if (flags & EXECFLG_OUTPUT) + xpipe(pipe_fm_child); + + child = fork(); + if (child == -1) { + perror_msg_and_die("fork"); + } + if (child == 0) { + /* Child */ + + /* Play with stdio descriptors */ + if (flags & EXECFLG_INPUT) { + xmove_fd(pipe_to_child[0], STDIN_FILENO); + } else if (flags & EXECFLG_INPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO); + } + if (flags & EXECFLG_OUTPUT) { + xmove_fd(pipe_fm_child[1], STDOUT_FILENO); + } else if (flags & EXECFLG_OUTPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDOUT_FILENO); + } + if (flags & EXECFLG_ERR2OUT) { + /* Want parent to see errors in the same stream */ + xdup2(STDOUT_FILENO, STDERR_FILENO); + } else if (flags & EXECFLG_ERR_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDERR_FILENO); + } + + if (flags & EXECFLG_SETGUID) { + struct passwd* pw = getpwuid(uid); + gid_t gid = pw ? pw->pw_gid : uid; + setgroups(1, &gid); + xsetregid(gid, gid); + xsetreuid(uid, uid); + } + if (flags & EXECFLG_SETSID) + setsid(); + + if (unsetenv_vec) { + while (*unsetenv_vec) + unsetenv(*unsetenv_vec++); + } + + if (dir) + xchdir(dir); + + execvp(argv[0], argv); + if (!(flags & EXECFLG_QUIET)) + perror_msg("Can't execute '%s'", argv[0]); + exit(127); /* shell uses this exitcode in this case */ + } + + if (flags & EXECFLG_INPUT) { + close(pipe_to_child[0]); + pipefds[1] = pipe_to_child[1]; + } + if (flags & EXECFLG_OUTPUT) { + close(pipe_fm_child[1]); + pipefds[0] = pipe_fm_child[0]; + } + + return child; +} + +char *run_in_shell_and_save_output(int flags, + const char *cmd, + const char *dir, + size_t *size_p) +{ + flags |= EXECFLG_OUTPUT; + flags &= ~EXECFLG_INPUT; + + const char *argv[] = { "/bin/sh", "sh", "-c", cmd, NULL }; + int pipeout[2]; + pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout, + /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0); + + size_t pos = 0; + char *result = NULL; + while (1) { + result = (char*) xrealloc(result, pos + 4*1024 + 1); + size_t sz = safe_read(pipeout[0], result + pos, 4*1024); + if (sz <= 0) { + break; + } + pos += sz; + } + result[pos] = '\0'; + if (size_p) + *size_p = pos; + close(pipeout[0]); + waitpid(child, NULL, 0); + + return result; +} diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index 8621b5f..3ab3739 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -141,6 +141,12 @@ off_t xlseek(int fd, off_t offset, int whence) return off; } +void xchdir(const char *path) +{ + if (chdir(path)) + perror_msg_and_die("chdir(%s)", path); +} + char* xvasprintf(const char *format, va_list p) { int r; -- cgit From 1d038a9cf5e154406710800c372631f5c7c3fd81 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:20:12 +0100 Subject: abrt-hook-python: add input sanitization and directory size guard Signed-off-by: Denys Vlasenko --- src/Hooks/CCpp.cpp | 85 ++++-------------------------- src/Hooks/Makefile.am | 8 +-- src/Hooks/abrt-hook-python.cpp | 39 ++++++++------ src/Hooks/hooklib.cpp | 116 +++++++++++++++++++++++++++++++++++++++++ src/Hooks/hooklib.h | 21 ++++++++ 5 files changed, 174 insertions(+), 95 deletions(-) create mode 100644 src/Hooks/hooklib.cpp create mode 100644 src/Hooks/hooklib.h diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index 3a13358..4935b34 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -19,9 +19,11 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "abrtlib.h" +#include "hooklib.h" #include "DebugDump.h" #include "ABRTException.h" #include +#include #define FILENAME_EXECUTABLE "executable" #define FILENAME_COREDUMP "coredump" @@ -63,9 +65,9 @@ int main(int argc, char** argv) int fd; struct stat sb; - const char* program_name = argv[0]; if (argc < 5) { + const char* program_name = argv[0]; error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); } openlog("abrt", 0, LOG_DAEMON); @@ -124,62 +126,13 @@ int main(int argc, char** argv) /* Parse abrt.conf and plugins/CCpp.conf */ unsigned setting_MaxCrashReportsSize = 0; bool setting_MakeCompatCore = false; - bool abrt_conf = true; - FILE *fp = fopen(CONF_DIR"/abrt.conf", "r"); - if (fp) - { - char line[256]; - while (1) - { - if (fgets(line, sizeof(line), fp) == NULL) - { - /* Next .conf file plz */ - if (abrt_conf) - { - abrt_conf = false; - fp = fopen(CONF_DIR"/plugins/CCpp.conf", "r"); - if (fp) - continue; - } - break; - } + parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore); - unsigned len = strlen(line); - if (len > 0 && line[len-1] == '\n') - line[--len] = '\0'; - const char *p = skip_whitespace(line); -#undef DIRECTIVE -#define DIRECTIVE "MaxCrashReportsSize" - if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) - { - p = skip_whitespace(p + sizeof(DIRECTIVE)-1); - if (*p != '=') - continue; - p = skip_whitespace(p + 1); - if (isdigit(*p)) - /* x1.25: go a bit up, so that usual in-daemon trimming - * kicks in first, and we don't "fight" with it. */ - setting_MaxCrashReportsSize = (unsigned long)xatou(p) * 5 / 4; - continue; - } -#undef DIRECTIVE -#define DIRECTIVE "MakeCompatCore" - if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) - { - p = skip_whitespace(p + sizeof(DIRECTIVE)-1); - if (*p != '=') - continue; - p = skip_whitespace(p + 1); - setting_MakeCompatCore = string_to_bool(p); - continue; - } -#undef DIRECTIVE - /* add more 'if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)' here... */ - } - fclose(fp); + if (setting_MaxCrashReportsSize > 0) + { + check_free_space(setting_MaxCrashReportsSize); } - char path[PATH_MAX]; /* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes @@ -288,30 +241,10 @@ int main(int argc, char** argv) */ dd.Close(); - /* rhbz#539551: "abrt going crazy when crashing process is respawned". - * Do we want to protect against or ameliorate this? How? Ideas: - * (1) nice ourself? - * (2) check total size of dump dir, if it overflows, either abort dump - * or delete oldest/biggest dumps? [abort would be simpler, - * abrtd already does "delete on overflow" thing] - * (3) detect parallel dumps in progress and back off - * (pause/renice further/??) - */ - + /* rhbz#539551: "abrt going crazy when crashing process is respawned" */ if (setting_MaxCrashReportsSize > 0) { - string worst_dir; - while (1) - { - const char *base_dirname = strrchr(path, '/') + 1; /* never NULL */ - /* We exclude our own dump from candidates for deletion (3rd param): */ - double dirsize = get_dirsize_find_largest_dir(DEBUG_DUMPS_DIR, &worst_dir, base_dirname); - if (dirsize / (1024*1024) < setting_MaxCrashReportsSize || worst_dir == "") - break; - log("size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, setting_MaxCrashReportsSize, worst_dir.c_str()); - delete_debug_dump_dir(concat_path_file(DEBUG_DUMPS_DIR, worst_dir.c_str()).c_str()); - worst_dir = ""; - } + trim_debug_dumps(setting_MaxCrashReportsSize, path); } if (!setting_MakeCompatCore) diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am index 7581971..ebabd87 100644 --- a/src/Hooks/Makefile.am +++ b/src/Hooks/Makefile.am @@ -1,9 +1,10 @@ libexec_PROGRAMS = abrt-hook-ccpp abrt-hook-python bin_PROGRAMS = dumpoops -# CCpp +# abrt-hook-ccpp abrt_hook_ccpp_SOURCES = \ - CCpp.cpp + CCpp.cpp \ + hooklib.h hooklib.cpp abrt_hook_ccpp_CPPFLAGS = \ -I$(srcdir)/../../inc \ -I$(srcdir)/../../lib/Utils \ @@ -34,7 +35,8 @@ dumpoops_LDADD = \ # abrt-hook-python abrt_hook_python_SOURCES = \ - abrt-hook-python.cpp + abrt-hook-python.cpp \ + hooklib.h hooklib.cpp abrt_hook_python_CPPFLAGS = \ -I$(srcdir)/../../inc \ -I$(srcdir)/../../lib/Utils \ diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index 3f79d28..406cd82 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -24,12 +24,14 @@ /* We can easily get rid of abrtlib (libABRTUtils.so) usage in this file, * but DebugDump will pull it in anyway */ #include "abrtlib.h" +#include "hooklib.h" #include "DebugDump.h" #if HAVE_CONFIG_H # include #endif #define MAX_BT_SIZE (1024*1024) +#define MAX_BT_SIZE_STR "1 MB" static char *pid; static char *executable; @@ -74,9 +76,15 @@ int main(int argc, char** argv) ); } } - if (!pid) + if (!pid || !executable || !uuid) goto usage; -// is it really ok if other params aren't specified? abrtd might get confused... + + unsigned setting_MaxCrashReportsSize = 0; + parse_conf(NULL, &setting_MaxCrashReportsSize, NULL); + if (setting_MaxCrashReportsSize > 0) + { + check_free_space(setting_MaxCrashReportsSize); + } // Read the backtrace from stdin char *bt = (char*)xmalloc(MAX_BT_SIZE); @@ -88,35 +96,34 @@ int main(int argc, char** argv) bt[len] = '\0'; if (len == MAX_BT_SIZE-1) { - error_msg("Backtrace size limit exceeded, trimming to 1 MB"); + error_msg("Backtrace size limit exceeded, trimming to " MAX_BT_SIZE_STR); } + char *cmdline = get_cmdline(xatou(pid)); /* never NULL */ + // Create directory with the debug dump char path[PATH_MAX]; snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s", (long)time(NULL), pid); - CDebugDump dd; dd.Create(path, geteuid()); - dd.SaveText(FILENAME_ANALYZER, "Python"); - if (executable) - dd.SaveText(FILENAME_EXECUTABLE, executable); - pid_t pidt = xatoi(pid); - char *cmdline = get_cmdline(pidt); + dd.SaveText(FILENAME_ANALYZER, "Python"); + dd.SaveText(FILENAME_EXECUTABLE, executable); + dd.SaveText("backtrace", bt); + free(bt); dd.SaveText("cmdline", cmdline); free(cmdline); - - if (uuid) - dd.SaveText("uuid", uuid); - + dd.SaveText("uuid", uuid); char uid[sizeof(int) * 3 + 2]; - sprintf(uid, "%d", (int)getuid()); + sprintf(uid, "%u", (unsigned)getuid()); dd.SaveText("uid", uid); - dd.SaveText("backtrace", bt); - free(bt); dd.Close(); + if (setting_MaxCrashReportsSize > 0) + { + trim_debug_dumps(setting_MaxCrashReportsSize, path); + } return 0; } diff --git a/src/Hooks/hooklib.cpp b/src/Hooks/hooklib.cpp new file mode 100644 index 0000000..41b9627 --- /dev/null +++ b/src/Hooks/hooklib.cpp @@ -0,0 +1,116 @@ +/* + 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 "abrtlib.h" +#include "hooklib.h" +#include "DebugDump.h" +#include + +using namespace std; + +void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore) +{ + FILE *fp = fopen(CONF_DIR"/abrt.conf", "r"); + if (!fp) + return; + + char line[256]; + while (1) + { + if (fgets(line, sizeof(line), fp) == NULL) + { + fclose(fp); + if (additional_conf) + { + /* Next .conf file plz */ + fp = fopen(additional_conf, "r"); + if (fp) + { + additional_conf = NULL; + continue; + } + } + break; + } + + unsigned len = strlen(line); + if (len > 0 && line[len-1] == '\n') + line[--len] = '\0'; + const char *p = skip_whitespace(line); +#undef DIRECTIVE +#define DIRECTIVE "MaxCrashReportsSize" + if (setting_MaxCrashReportsSize && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) + { + p = skip_whitespace(p + sizeof(DIRECTIVE)-1); + if (*p != '=') + continue; + p = skip_whitespace(p + 1); + if (isdigit(*p)) + { + /* x1.25: go a bit up, so that usual in-daemon trimming + * kicks in first, and we don't "fight" with it. */ + *setting_MaxCrashReportsSize = (unsigned long)xatou(p) * 5 / 4; + } + continue; + } +#undef DIRECTIVE +#define DIRECTIVE "MakeCompatCore" + if (setting_MakeCompatCore && strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0) + { + p = skip_whitespace(p + sizeof(DIRECTIVE)-1); + if (*p != '=') + continue; + p = skip_whitespace(p + 1); + *setting_MakeCompatCore = string_to_bool(p); + continue; + } +#undef DIRECTIVE + /* add more 'if (strncmp(p, DIRECTIVE, sizeof(DIRECTIVE)-1) == 0)' here... */ + } +} + +void check_free_space(unsigned setting_MaxCrashReportsSize) +{ + /* Check that at least MaxCrashReportsSize/4 MBs are free. */ + struct statvfs vfs; + if (statvfs(DEBUG_DUMPS_DIR, &vfs) != 0 + || (vfs.f_bfree / (1024*1024 / 4)) * vfs.f_bsize < setting_MaxCrashReportsSize + ) { + error_msg_and_die("Low free disk space detected, aborting dump"); + } +} + +/* rhbz#539551: "abrt going crazy when crashing process is respawned". + * Check total size of dump dir, if it overflows, + * delete oldest/biggest dumps. + */ +void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path) +{ + int count = 10; + string worst_dir; + while (--count >= 0) + { + const char *base_dirname = strrchr(exclude_path, '/') + 1; /* never NULL */ + /* We exclude our own dump from candidates for deletion (3rd param): */ + double dirsize = get_dirsize_find_largest_dir(DEBUG_DUMPS_DIR, &worst_dir, base_dirname); + if (dirsize / (1024*1024) < setting_MaxCrashReportsSize || worst_dir == "") + break; + log("size of '%s' >= %u MB, deleting '%s'", DEBUG_DUMPS_DIR, setting_MaxCrashReportsSize, worst_dir.c_str()); + delete_debug_dump_dir(concat_path_file(DEBUG_DUMPS_DIR, worst_dir.c_str()).c_str()); + worst_dir = ""; + } +} diff --git a/src/Hooks/hooklib.h b/src/Hooks/hooklib.h new file mode 100644 index 0000000..0794ff6 --- /dev/null +++ b/src/Hooks/hooklib.h @@ -0,0 +1,21 @@ +/* + 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. +*/ + +void parse_conf(const char *additional_conf, unsigned *setting_MaxCrashReportsSize, bool *setting_MakeCompatCore); +void check_free_space(unsigned setting_MaxCrashReportsSize); +void trim_debug_dumps(unsigned setting_MaxCrashReportsSize, const char *exclude_path); -- cgit From c2009ddeb7052dfe443f0239893f627759580c29 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:20:57 +0100 Subject: SOSreport/TicketUploader: use more restrictive file modes Signed-off-by: Denys Vlasenko --- inc/abrtlib.h | 2 +- lib/Plugins/SOSreport.cpp | 3 ++- lib/Plugins/TicketUploader.cpp | 2 +- lib/Utils/copyfd.cpp | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/inc/abrtlib.h b/inc/abrtlib.h index fadd7f1..8cb32d3 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -157,7 +157,7 @@ void xunlink(const char *pathname); off_t copyfd_eof(int src_fd, int dst_fd); off_t copyfd_size(int src_fd, int dst_fd, off_t size); void copyfd_exact_size(int src_fd, int dst_fd, off_t size); -off_t copy_file(const char *src_name, const char *dst_name); +off_t copy_file(const char *src_name, const char *dst_name, int mode); void xsetreuid(uid_t ruid, uid_t euid); diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp index 899b446..2576910 100644 --- a/lib/Plugins/SOSreport.cpp +++ b/lib/Plugins/SOSreport.cpp @@ -103,8 +103,9 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) dd.Open(pActionDir); //Not useful //dd.SaveText("sosreportoutput", output); - if (copy_file(sosreport_filename.c_str(), sosreport_dd_filename.c_str()) < 0) + if (copy_file(sosreport_filename.c_str(), sosreport_dd_filename.c_str(), 0644) < 0) { + dd.Close(); throw CABRTException(EXCEP_PLUGIN, "Can't copy '%s' to '%s'", sosreport_filename.c_str(), diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp index a4fe0e8..de19791 100644 --- a/lib/Plugins/TicketUploader.cpp +++ b/lib/Plugins/TicketUploader.cpp @@ -221,7 +221,7 @@ string CTicketUploader::Report(const map_crash_report_t& pCrashReport, else if (it->second[CD_TYPE] == CD_BIN) { string ofile_name = concat_path_file(tmptar_name.c_str(), it->first.c_str()); - if (copy_file(it->second[CD_CONTENT].c_str(), ofile_name.c_str()) < 0) + if (copy_file(it->second[CD_CONTENT].c_str(), ofile_name.c_str(), 0644) < 0) { throw CABRTException(EXCEP_PLUGIN, "Can't copy '%s' to '%s'", diff --git a/lib/Utils/copyfd.cpp b/lib/Utils/copyfd.cpp index 9abe752..fdc568a 100644 --- a/lib/Utils/copyfd.cpp +++ b/lib/Utils/copyfd.cpp @@ -106,7 +106,7 @@ off_t copyfd_eof(int fd1, int fd2) return full_fd_action(fd1, fd2, 0); } -off_t copy_file(const char *src_name, const char *dst_name) +off_t copy_file(const char *src_name, const char *dst_name, int mode) { off_t r; int src = open(src_name, O_RDONLY); @@ -115,7 +115,7 @@ off_t copy_file(const char *src_name, const char *dst_name) perror_msg("Can't open '%s'", src_name); return -1; } - int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, 0666); + int dst = open(dst_name, O_WRONLY | O_TRUNC | O_CREAT, mode); if (dst < 0) { close(src); -- cgit From b1c4304104910c4bc066cd43f9784fe2f3ddf1ad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:21:31 +0100 Subject: *: cast pids and uigs to long, not int Signed-off-by: Denys Vlasenko --- lib/Plugins/CCpp.cpp | 2 +- lib/Plugins/Firefox.cpp | 2 +- lib/Utils/DebugDump.cpp | 6 +++--- lib/Utils/daemon.cpp | 4 ++-- lib/Utils/xfuncs.cpp | 4 ++-- src/Daemon/Daemon.cpp | 4 ++-- src/Daemon/PluginManager.cpp | 4 ++-- src/Hooks/CCpp.cpp | 26 +++++++++++++------------- src/Hooks/abrt-hook-python.cpp | 4 ++-- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 26562be..a7f005c 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -368,7 +368,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir); /* SELinux guys are not happy with /tmp, using /var/run/abrt */ - char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL)); + char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu", (long)getpid(), (long)time(NULL)); /* log() goes to stderr/syslog, it's ok to use it here */ VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs); /* We want parent to see errors in the same stream */ diff --git a/lib/Plugins/Firefox.cpp b/lib/Plugins/Firefox.cpp index 92ef4e5..cd02a15 100644 --- a/lib/Plugins/Firefox.cpp +++ b/lib/Plugins/Firefox.cpp @@ -692,7 +692,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir); /* SELinux guys are not happy with /tmp, using /var/run/abrt */ - char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%u-%lu", (int)getpid(), (long)time(NULL)); + char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu", (long)getpid(), (long)time(NULL)); /* log() goes to stderr/syslog, it's ok to use it here */ VERB1 log("Executing: %s %s %s %s", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR); execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, DEBUGINFO_CACHE_DIR, NULL); diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index 86e198c..cb3a082 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -209,8 +209,8 @@ void CDebugDump::Lock() error_msg_and_die("Locking bug on '%s'", m_sDebugDumpDir.c_str()); std::string lockFile = m_sDebugDumpDir + ".lock"; - char pid_buf[sizeof(int)*3 + 2]; - sprintf(pid_buf, "%u", (unsigned)getpid()); + 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 */ @@ -267,7 +267,7 @@ void CDebugDump::Create(const char *pDir, int64_t uid) { /* if /var/cache/abrt is writable by all, _aborting_ here is not useful */ /* let's just warn */ - perror_msg("can't change '%s' ownership to %u:%u", m_sDebugDumpDir.c_str(), (int)uid, (int)gid); + perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(), (long)uid, (long)gid); } SaveText(FILENAME_UID, to_string(uid).c_str()); diff --git a/lib/Utils/daemon.cpp b/lib/Utils/daemon.cpp index 7aa891c..0527062 100644 --- a/lib/Utils/daemon.cpp +++ b/lib/Utils/daemon.cpp @@ -78,12 +78,12 @@ static char *append_escaped(char *start, const char *s) #define COMMAND_LINE_SIZE 2048 char* get_cmdline(pid_t pid) { - char path[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; + char path[sizeof("/proc/%lu/cmdline") + sizeof(long)*3]; char cmdline[COMMAND_LINE_SIZE]; char escaped_cmdline[COMMAND_LINE_SIZE*4 + 4]; escaped_cmdline[1] = '\0'; - sprintf(path, "/proc/%u/cmdline", (int)pid); + sprintf(path, "/proc/%lu/cmdline", (long)pid); int fd = open(path, O_RDONLY); if (fd >= 0) { diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index 3ab3739..7ffbb2d 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -371,13 +371,13 @@ bool string_to_bool(const char *s) void xsetreuid(uid_t ruid, uid_t euid) { if (setreuid(ruid, euid) != 0) - perror_msg_and_die("can't set %cid %d", 'u', (int)ruid); + perror_msg_and_die("can't set %cid %lu", 'u', (long)ruid); } void xsetregid(gid_t rgid, uid_t egid) { if (setregid(rgid, egid) != 0) - perror_msg_and_die("can't set %cid %d", 'g', (int)rgid); + perror_msg_and_die("can't set %cid %lu", 'g', (long)rgid); } uid_t getuidbyname(const char* login) diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 7577611..9e1aa0d 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -361,8 +361,8 @@ static int CreatePidFile() if (fd >= 0) { /* write our pid to it */ - char buf[sizeof(int)*3 + 2]; - int len = sprintf(buf, "%u\n", (unsigned)getpid()); + char buf[sizeof(long)*3 + 2]; + int len = sprintf(buf, "%lu\n", (long)getpid()); write(fd, buf, len); close(fd); return 0; diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 4aef630..697b964 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -412,7 +412,7 @@ void CPluginManager::SetPluginSettings(const char *pName, } if (chown(confDir.c_str(), uid, gid) == -1) { - perror_msg("Can't change '%s' ownership to %u:%u", confPath.c_str(), (int)uid, (int)gid); + perror_msg("Can't change '%s' ownership to %lu:%lu", confPath.c_str(), (long)uid, (long)gid); return; } } @@ -430,7 +430,7 @@ void CPluginManager::SetPluginSettings(const char *pName, SavePluginSettings(confPath, pSettings); if (chown(confPath.c_str(), uid, gid) == -1) { - perror_msg("Can't change '%s' ownership to %u:%u", confPath.c_str(), (int)uid, (int)gid); + perror_msg("Can't change '%s' ownership to %lu:%lu", confPath.c_str(), (long)uid, (long)gid); return; } */ diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index 4935b34..b09a132 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -46,17 +46,17 @@ static char* malloc_readlink(const char *linkname) static char* get_executable(pid_t pid) { - char buf[sizeof("/proc/%u/exe") + sizeof(int)*3]; + char buf[sizeof("/proc/%lu/exe") + sizeof(long)*3]; - sprintf(buf, "/proc/%u/exe", (int)pid); + sprintf(buf, "/proc/%lu/exe", (long)pid); return malloc_readlink(buf); } static char* get_cwd(pid_t pid) { - char buf[sizeof("/proc/%u/cwd") + sizeof(int)*3]; + char buf[sizeof("/proc/%lu/cwd") + sizeof(long)*3]; - sprintf(buf, "/proc/%u/cwd", (int)pid); + sprintf(buf, "/proc/%lu/cwd", (long)pid); return malloc_readlink(buf); } @@ -115,12 +115,12 @@ int main(int argc, char** argv) char* executable = get_executable(pid); if (executable == NULL) { - error_msg_and_die("can't read /proc/%u/exe link", (int)pid); + error_msg_and_die("can't read /proc/%lu/exe link", (long)pid); } if (strstr(executable, "/abrt-hook-ccpp")) { - error_msg_and_die("pid %u is '%s', not dumping it to avoid recursion", - (int)pid, executable); + error_msg_and_die("pid %lu is '%s', not dumping it to avoid recursion", + (long)pid, executable); } /* Parse abrt.conf and plugins/CCpp.conf */ @@ -185,7 +185,7 @@ int main(int argc, char** argv) * but it does not log file name */ error_msg_and_die("error saving coredump to %s", path); } - log("saved core dump of pid %u (%s) to %s (%llu bytes)", (int)pid, executable, path, (long long)core_size); + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); return 0; } @@ -193,7 +193,7 @@ int main(int argc, char** argv) const char *signame = strsignal(signal_no); char *reason = xasprintf("Process was terminated by signal %s (%s)", signal_str, signame ? signame : signal_str); - snprintf(path, sizeof(path), "%s/ccpp-%ld-%u", dddir, (long)time(NULL), (int)pid); + snprintf(path, sizeof(path), "%s/ccpp-%ld-%lu", dddir, (long)time(NULL), (long)pid); CDebugDump dd; dd.Create(path, uid); dd.SaveText(FILENAME_ANALYZER, "CCpp"); @@ -228,7 +228,7 @@ int main(int argc, char** argv) } lseek(core_fd, 0, SEEK_SET); /* note: core_fd is still open, we may use it later to copy core to user's dir */ - log("saved core dump of pid %u (%s) to %s (%llu bytes)", (int)pid, executable, path, (long long)core_size); + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); free(executable); free(cmdline); path[len] = '\0'; /* path now contains directory name */ @@ -282,7 +282,7 @@ int main(int argc, char** argv) } /* Mimic "core.PID" if requested */ - char core_basename[sizeof("core.%u") + sizeof(int)*3] = "core"; + char core_basename[sizeof("core.%lu") + sizeof(long)*3] = "core"; char buf[] = "0\n"; fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY); if (fd >= 0) @@ -292,7 +292,7 @@ int main(int argc, char** argv) } if (strcmp(buf, "1\n") == 0) { - sprintf(core_basename, "core.%u", (int)pid); + sprintf(core_basename, "core.%lu", (long)pid); } /* man core: @@ -358,7 +358,7 @@ int main(int argc, char** argv) unlink(core_basename); return 1; } - log("saved core dump of pid %u to %s/%s (%llu bytes)", (int)pid, user_pwd, core_basename, (long long)size); + log("saved core dump of pid %lu to %s/%s (%llu bytes)", (long)pid, user_pwd, core_basename, (long long)size); return 0; } diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index 406cd82..468c7ec 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -115,8 +115,8 @@ int main(int argc, char** argv) dd.SaveText("cmdline", cmdline); free(cmdline); dd.SaveText("uuid", uuid); - char uid[sizeof(int) * 3 + 2]; - sprintf(uid, "%u", (unsigned)getuid()); + char uid[sizeof(long) * 3 + 2]; + sprintf(uid, "%lu", (long)getuid()); dd.SaveText("uid", uid); dd.Close(); -- cgit From 14ef0cfe72faf6696df3ef8f42927e9458ccbeeb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 07:22:13 +0100 Subject: *: misc fixes Signed-off-by: Denys Vlasenko --- lib/Plugins/CCpp.cpp | 2 +- lib/Plugins/FileTransfer.cpp | 20 ++++++-------------- lib/Plugins/RunApp.cpp | 4 ++++ lib/Utils/CommLayerInner.cpp | 6 ++---- lib/Utils/DebugDump.cpp | 10 +++++++++- lib/Utils/DebugDump.h | 2 +- lib/Utils/Polkit.cpp | 10 ++++++++-- lib/Utils/xatonum.cpp | 4 ++-- src/Applet/CCApplet.cpp | 2 +- src/Daemon/CrashWatcher.cpp | 12 +++++------- src/Daemon/abrt-debuginfo-install | 6 ++++-- src/Hooks/CCpp.cpp | 2 +- src/Hooks/abrt-hook-python.cpp | 2 ++ 13 files changed, 46 insertions(+), 36 deletions(-) diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index a7f005c..46c2f28 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -627,7 +627,7 @@ static bool DebuginfoCheckPolkit(int uid) //parent int status; - if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0) + if (waitpid(child_pid, &status, 0) > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { return true; //authorization OK } diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp index 60e1e66..9d7a59a 100644 --- a/lib/Plugins/FileTransfer.cpp +++ b/lib/Plugins/FileTransfer.cpp @@ -110,13 +110,11 @@ parameter "something" to each filename, now used in create_zip, but can be useful for some future archivers as well */ -static void traverse_directory(const char * directory, void * something, - void (*func)(void *, const char *) ) +static void traverse_directory(const char *directory, void *something, + void (*func)(void *, const char *)) { - DIR * dp; - struct dirent * dirp; - char complete_name[BUFSIZ]; - char * end; + DIR *dp; + struct dirent *dirp; dp = opendir(directory); if (dp == NULL) @@ -127,14 +125,8 @@ static void traverse_directory(const char * directory, void * something, { if (is_regular_file(dirp, directory)) { - end = stpcpy(complete_name, directory); - if (end[-1] != '/') - { - *end++ = '/'; - } - end = stpcpy(end, dirp->d_name); - - func(something, complete_name); + string complete_name = concat_path_file(directory, dirp->d_name); + func(something, complete_name.c_str()); } } closedir(dp); diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp index c1f725b..e2147e2 100644 --- a/lib/Plugins/RunApp.cpp +++ b/lib/Plugins/RunApp.cpp @@ -40,6 +40,10 @@ void CActionRunApp::Run(const char *pActionDir, const char *pArgs) vector_string_t args; parse_args(pArgs, args, '"'); + if (args.size() <= COMMAND) + { + return; + } const char *cmd = args[COMMAND].c_str(); if (!cmd[0]) { diff --git a/lib/Utils/CommLayerInner.cpp b/lib/Utils/CommLayerInner.cpp index 133e97d..4a3b80a 100644 --- a/lib/Utils/CommLayerInner.cpp +++ b/lib/Utils/CommLayerInner.cpp @@ -68,11 +68,9 @@ void update_client(const char *fmt, ...) va_list p; va_start(p, fmt); - char *msg; - int used = vasprintf(&msg, fmt, p); + char *msg = xvasprintf(fmt, p); va_end(p); - if (used < 0) - return; s_pObs->Status(msg, peer, key); + free(msg); } diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index cb3a082..dd992aa 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -115,7 +115,15 @@ static bool GetAndSetLock(const char* pLockFile, const char* pPID) 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) @@ -228,7 +236,7 @@ void CDebugDump::UnLock() } } -void CDebugDump::Create(const char *pDir, int64_t uid) +void CDebugDump::Create(const char *pDir, uid_t uid) { if (m_bOpened) { diff --git a/lib/Utils/DebugDump.h b/lib/Utils/DebugDump.h index c59552e..ce515db 100644 --- a/lib/Utils/DebugDump.h +++ b/lib/Utils/DebugDump.h @@ -62,7 +62,7 @@ class CDebugDump ~CDebugDump(); void Open(const char *pDir); - void Create(const char *pDir, int64_t uid); + void Create(const char *pDir, uid_t uid); void Delete(); void Close(); diff --git a/lib/Utils/Polkit.cpp b/lib/Utils/Polkit.cpp index c868e1a..8bd0eb6 100644 --- a/lib/Utils/Polkit.cpp +++ b/lib/Utils/Polkit.cpp @@ -46,14 +46,12 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id) GCancellable * cancellable; authority = polkit_authority_get(); - cancellable = g_cancellable_new(); g_timeout_add(POLKIT_TIMEOUT * 1000, (GSourceFunc) do_cancel, cancellable); - result = polkit_authority_check_authorization_sync(authority, subject, action_id, @@ -61,6 +59,7 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id) POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, cancellable, &error); + g_object_unref(authority); if (error) { @@ -71,11 +70,18 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id) if (result) { if (polkit_authorization_result_get_is_challenge(result)) + { /* Can't happen (happens only with * POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE flag) */ + g_object_unref(result); return PolkitChallenge; + } if (polkit_authorization_result_get_is_authorized(result)) + { + g_object_unref(result); return PolkitYes; + } + g_object_unref(result); return PolkitNo; } diff --git a/lib/Utils/xatonum.cpp b/lib/Utils/xatonum.cpp index b096ca8..8314629 100644 --- a/lib/Utils/xatonum.cpp +++ b/lib/Utils/xatonum.cpp @@ -9,7 +9,7 @@ unsigned xatou(const char *numstr) { - unsigned r; + unsigned long r; int old_errno; char *e; @@ -19,7 +19,7 @@ unsigned xatou(const char *numstr) old_errno = errno; errno = 0; r = strtoul(numstr, &e, 10); - if (errno || numstr == e || *e != '\0') + if (errno || numstr == e || *e != '\0' || r > UINT_MAX) goto inval; /* error / no digits / illegal trailing chars */ errno = old_errno; /* Ok. So restore errno. */ return r; diff --git a/src/Applet/CCApplet.cpp b/src/Applet/CCApplet.cpp index 07e44d8..770915a 100644 --- a/src/Applet/CCApplet.cpp +++ b/src/Applet/CCApplet.cpp @@ -205,7 +205,7 @@ void CApplet::CrashNotify(const char *format, ...) if (gtk_status_icon_is_embedded(m_pStatusIcon)) notify_notification_show(m_pNotification, &err); if (err != NULL) - error_msg(err->message); + error_msg("%s", err->message); } void CApplet::OnAppletActivate_CB(GtkStatusIcon *status_icon, gpointer user_data) diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp index 88c058b..59f9e65 100644 --- a/src/Daemon/CrashWatcher.cpp +++ b/src/Daemon/CrashWatcher.cpp @@ -168,12 +168,11 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha thread_data->force = force; thread_data->peer = xstrdup(pSender); -//TODO: do we need this? -//pthread_attr_t attr; -//pthread_attr_init(&attr); -//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - int r = pthread_create(&thread_data->thread_id, NULL, create_report, thread_data); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + int r = pthread_create(&thread_data->thread_id, &attr, create_report, thread_data); + pthread_attr_destroy(&attr); if (r != 0) { free(thread_data->UUID); @@ -187,7 +186,6 @@ int CreateReportThread(const char* pUUID, const char* pUID, int force, const cha return r; } VERB3 log("Thread %llx created", (unsigned long long)thread_data->thread_id); -//pthread_attr_destroy(&attr); return r; } diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index cfae49a..35f4d6a 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -145,9 +145,11 @@ print_package_names() { fi # when we look for debuginfo we need only -debuginfo* repos, so we can disable the rest and thus make it faster # also we want only fedora repositories, because abrt won't work for other packages anyway - local cmd="yum $yumopts --disablerepo=* --enablerepo=fedora-debuginfo* --enablerepo=updates-debuginfo* --quiet provides $missing_debuginfo_files" + local cmd="yum $yumopts '--disablerepo=*' '--enablerepo=fedora-debuginfo*' '--enablerepo=updates-debuginfo*' --quiet provides $missing_debuginfo_files" echo "$cmd" >"yum_provides.$1.OUT" - local yum_provides_OUT="`$cmd 2>&1`" + # eval is needed to strip away ''s; cant remove them above and just use + # $cmd, that would perform globbing on '*' + local yum_provides_OUT="`eval $cmd 2>&1`" local err=$? printf "%s\nyum exitcode:%s\n" "$yum_provides_OUT" $err >>"yum_provides.$1.OUT" test $err = 0 || error_msg_and_die "yum provides... exited with $err: diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index b09a132..b5bfff7 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -70,7 +70,7 @@ int main(int argc, char** argv) const char* program_name = argv[0]; error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); } - openlog("abrt", 0, LOG_DAEMON); + openlog("abrt", 0, LOG_PID | LOG_DAEMON); logmode = LOGMODE_SYSLOG; errno = 0; diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index 468c7ec..1a7eace 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -79,6 +79,8 @@ int main(int argc, char** argv) if (!pid || !executable || !uuid) goto usage; +//TODO: sanitize uuid and executable (size, valid chars etc) + unsigned setting_MaxCrashReportsSize = 0; parse_conf(NULL, &setting_MaxCrashReportsSize, NULL); if (setting_MaxCrashReportsSize > 0) -- cgit From edf6beb585dc38c365ccbdaae85756b2814e1329 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 12:09:57 +0100 Subject: *: assorted fixes prompted by security analysis; more to come Signed-off-by: Denys Vlasenko --- inc/abrtlib.h | 2 +- lib/Plugins/CCpp.cpp | 12 +++++++++--- lib/Plugins/Catcut.cpp | 16 ++++++++-------- lib/Plugins/FileTransfer.cpp | 11 +++++------ lib/Plugins/Firefox.cpp | 13 ++++++++++--- lib/Plugins/KerneloopsScanner.cpp | 4 +++- lib/Plugins/Mailx.cpp | 33 ++++++++------------------------- lib/Plugins/SQLite3.cpp | 8 ++++---- lib/Plugins/TicketUploader.cpp | 7 ++----- lib/Utils/DebugDump.cpp | 2 +- lib/Utils/abrt_dbus.h | 3 +++ lib/Utils/spawn.cpp | 1 + lib/Utils/xfuncs.cpp | 4 ++-- src/Applet/CCApplet.cpp | 11 ++++++----- src/Daemon/Daemon.cpp | 8 +++++--- src/Daemon/MiddleWare.cpp | 2 ++ src/Daemon/PluginManager.cpp | 2 ++ src/Daemon/RPM.cpp | 4 ++-- src/Hooks/CCpp.cpp | 2 +- src/Hooks/dumpoops.cpp | 1 + 20 files changed, 76 insertions(+), 70 deletions(-) diff --git a/inc/abrtlib.h b/inc/abrtlib.h index 8cb32d3..ed54b52 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -161,7 +161,7 @@ off_t copy_file(const char *src_name, const char *dst_name, int mode); void xsetreuid(uid_t ruid, uid_t euid); -void xsetregid(gid_t rgid, uid_t egid); +void xsetregid(gid_t rgid, gid_t egid); enum { EXECFLG_INPUT = 1 << 0, EXECFLG_OUTPUT = 1 << 1, diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 46c2f28..4bf1bc1 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -353,6 +353,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, int pipeout[2]; //TODO: can we use ExecVP? xpipe(pipeout); + fflush(NULL); pid_t child = fork(); if (child < 0) { @@ -548,6 +549,8 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) int pipeout[2]; xpipe(pipeout); /* stdout of abrt-backtrace */ + + fflush(NULL); pid_t child = fork(); if (child == -1) perror_msg_and_die("fork"); @@ -609,8 +612,9 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) return CreateHash(hash_base.c_str()); } -static bool DebuginfoCheckPolkit(int uid) +static bool DebuginfoCheckPolkit(uid_t uid) { + fflush(NULL); int child_pid = fork(); if (child_pid < 0) { @@ -627,8 +631,10 @@ static bool DebuginfoCheckPolkit(int uid) //parent int status; - if (waitpid(child_pid, &status, 0) > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0) - { + if (waitpid(child_pid, &status, 0) > 0 + && WIFEXITED(status) + && WEXITSTATUS(status) == 0 + ) { return true; //authorization OK } log("UID %d is not authorized to install debuginfos", uid); diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp index a56015d..52efc57 100644 --- a/lib/Plugins/Catcut.cpp +++ b/lib/Plugins/Catcut.cpp @@ -13,7 +13,7 @@ using namespace std; static int -put_stream(const char *pURL, FILE* f, size_t content_length) +put_stream(const char *pURL, FILE* f, off_t content_length) { CURL* curl = xcurl_easy_init(); /* enable uploading */ @@ -22,8 +22,8 @@ put_stream(const char *pURL, FILE* f, size_t content_length) curl_easy_setopt(curl, CURLOPT_URL, pURL); /* file handle: passed to the default callback, it will fread() it */ curl_easy_setopt(curl, CURLOPT_READDATA, f); - /* get file size */ - curl_easy_setopt(curl, CURLOPT_INFILESIZE, content_length); + /* file size */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)content_length); /* everything is done here; result 0 means success */ int result = curl_easy_perform(curl); /* goodbye */ @@ -43,9 +43,9 @@ send_string(const char *pURL, return; } + size_t content_length = strlen(pContent); while (1) { - int content_length = strlen(pContent); FILE* f = fmemopen((void*)pContent, content_length, "r"); if (!f) { @@ -53,7 +53,7 @@ send_string(const char *pURL, } int result = put_stream(pURL, f, content_length); fclose(f); - if (!result) + if (result == 0) return; update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result)); if (--retryCount <= 0) @@ -88,10 +88,9 @@ send_file(const char *pURL, } struct stat buf; fstat(fileno(f), &buf); /* can't fail */ - int content_length = buf.st_size; - int result = put_stream(pURL, f, content_length); + int result = put_stream(pURL, f, buf.st_size); fclose(f); - if (!result) + if (result == 0) return; update_client(_("Sending failed, try it again: %s"), curl_easy_strerror((CURLcode)result)); if (--retryCount <= 0) @@ -122,6 +121,7 @@ resolve_relative_url(const char *url, const char *base) } const char *end_of_protocol = strchr(base, ':'); +//TODO: why is this safe?!! string protocol(base, end_of_protocol - base); end_of_protocol += 3; /* skip "://" */ diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp index 9d7a59a..b08ecd5 100644 --- a/lib/Plugins/FileTransfer.cpp +++ b/lib/Plugins/FileTransfer.cpp @@ -80,11 +80,7 @@ void CFileTransfer::SendFile(const char *pURL, const char *pFilename) { throw CABRTException(EXCEP_PLUGIN, "Can't open archive file '%s'", pFilename); } - if (fstat(fileno(f), &buf) == -1) - { - fclose(f); - throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename); - } + fstat(fileno(f), &buf); /* never fails */ curl = xcurl_easy_init(); /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -92,7 +88,7 @@ void CFileTransfer::SendFile(const char *pURL, const char *pFilename) curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str()); /* FILE handle: passed to the default callback, it will fread() it */ curl_easy_setopt(curl, CURLOPT_READDATA, f); - curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size); + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)buf.st_size); /* everything is done here; result 0 means success */ int result = curl_easy_perform(curl); curl_easy_cleanup(curl); @@ -181,6 +177,7 @@ static void create_targz(const char * archive_name, const char * directory) f = fopen(name_without_gz, "r"); if (f == NULL) { +//TODO: we leak uncompressed tar file on disk?? free(name_without_gz); return; } @@ -226,6 +223,7 @@ static void create_tarbz2(const char * archive_name, const char * directory) f = fopen(archive_name, "w"); if (f == NULL) { +//TODO: we leak uncompressed tar file on disk?? close(tarFD); free(name_without_bz2); return; @@ -312,6 +310,7 @@ void CFileTransfer::Run(const char *pActionDir, const char *pArgs) else if (strcmp(pArgs, "one") == 0) { /* just send one archive */ +//TODO: where are we creating it??!! In cwd, which may well be / ??!!! string archivename = ssprintf("%s-%s%s", hostname, DirBase(pActionDir).c_str(), m_sArchiveType.c_str()); try { diff --git a/lib/Plugins/Firefox.cpp b/lib/Plugins/Firefox.cpp index cd02a15..d980755 100644 --- a/lib/Plugins/Firefox.cpp +++ b/lib/Plugins/Firefox.cpp @@ -99,6 +99,8 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) pid_t child; xpipe(pipeout); + + fflush(NULL); child = fork(); if (child == -1) { @@ -549,6 +551,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) xpipe(pipein); xpipe(pipeout); + fflush(NULL); pid_t child = fork(); if (child < 0) { @@ -673,6 +676,7 @@ static void InstallDebugInfos(const char *pDebugDumpDir, std::string& build_ids) int pipeout[2]; //TODO: can we use ExecVP? xpipe(pipeout); + fflush(NULL); pid_t child = fork(); if (child < 0) { @@ -839,8 +843,9 @@ std::string CAnalyzerFirefox::GetGlobalUUID(const char *pDebugDumpDir) return CreateHash(package + executable + independentBacktrace); } -static bool DebuginfoCheckPolkit(int uid) +static bool DebuginfoCheckPolkit(uid_t uid) { + fflush(NULL); int child_pid = fork(); if (child_pid < 0) { @@ -857,8 +862,10 @@ static bool DebuginfoCheckPolkit(int uid) //parent int status; - if (waitpid(child_pid, &status, 0) > 0 && WEXITSTATUS(status) == 0) - { + if (waitpid(child_pid, &status, 0) > 0 + && WIFEXITED(status) + && WEXITSTATUS(status) == 0 + ) { return true; //authorization OK } log("UID %d is not authorized to install debuginfos", uid); diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp index 128e083..f05f0d8 100644 --- a/lib/Plugins/KerneloopsScanner.cpp +++ b/lib/Plugins/KerneloopsScanner.cpp @@ -147,8 +147,10 @@ int CKerneloopsScanner::ScanSysLogFile(const char *filename) if (fd < 0) return 0; statb.st_size = 0; /* paranoia */ - if (fstat(fd, &statb) != 0 || statb.st_size < 1) + if (fstat(fd, &statb) != 0 || statb.st_size < 1) { + close(fd); return 0; + } /* * in theory there's a race here, since someone could spew diff --git a/lib/Plugins/Mailx.cpp b/lib/Plugins/Mailx.cpp index 70eddb8..df33e84 100644 --- a/lib/Plugins/Mailx.cpp +++ b/lib/Plugins/Mailx.cpp @@ -39,33 +39,16 @@ CMailx::CMailx() : static void exec_and_feed_input(uid_t uid, const char* pText, char **pArgs) { int pipein[2]; - pid_t child; - xpipe(pipein); - child = fork(); - if (child == -1) - { - close(pipein[0]); - close(pipein[1]); - throw CABRTException(EXCEP_PLUGIN, "Can't fork"); - } - if (child == 0) - { - close(pipein[1]); - xmove_fd(pipein[0], STDIN_FILENO); - - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - setgroups(1, &gid); - xsetregid(gid, gid); - xsetreuid(uid, uid); - - execvp(pArgs[0], pArgs); - exit(1); /* exec failed */ - } + pid_t child = fork_execv_on_steroids( + EXECFLG_INPUT | EXECFLG_QUIET | EXECFLG_SETGUID, + pArgs, + pipein, + /*unsetenv_vec:*/ NULL, + /*dir:*/ NULL, + uid); - close(pipein[0]); - safe_write(pipein[1], pText, strlen(pText)); + full_write(pipein[1], pText, strlen(pText)); close(pipein[1]); waitpid(child, NULL, 0); /* wait for command completion */ diff --git a/lib/Plugins/SQLite3.cpp b/lib/Plugins/SQLite3.cpp index 0963456..ffcf05f 100644 --- a/lib/Plugins/SQLite3.cpp +++ b/lib/Plugins/SQLite3.cpp @@ -375,15 +375,15 @@ void CSQLite3::DeleteRow(const char *pUUID, const char *pUID) execute_sql(m_pDB, "DELETE FROM "ABRT_TABLE" " "WHERE "COL_UUID" = '%s';", - pUUID, pUID + pUUID ); } else if (exists_uuid_uid(m_pDB, pUUID, pUID)) { execute_sql(m_pDB, "DELETE FROM "ABRT_TABLE" " - "WHERE "COL_UUID" = '%s' " - "AND ("COL_UID" = '%s' OR "COL_UID" = '-1');", - pUUID, pUID + "WHERE "COL_UUID" = '%s' " + "AND ("COL_UID" = '%s' OR "COL_UID" = '-1');", + pUUID, pUID ); } else diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp index de19791..3fb7bcd 100644 --- a/lib/Plugins/TicketUploader.cpp +++ b/lib/Plugins/TicketUploader.cpp @@ -120,17 +120,14 @@ void CTicketUploader::SendFile(const char *pURL, const char *pFilename) throw CABRTException(EXCEP_PLUGIN, "Can't open archive file '%s'", pFilename); } struct stat buf; - if (fstat(fileno(f), &buf) == -1) /* TODO: never fails */ - { - throw CABRTException(EXCEP_PLUGIN, "Can't stat archive file '%s'", pFilename); - } + fstat(fileno(f), &buf); /* never fails */ CURL* curl = xcurl_easy_init(); /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* specify target */ curl_easy_setopt(curl, CURLOPT_URL, wholeURL.c_str()); curl_easy_setopt(curl, CURLOPT_READDATA, f); - curl_easy_setopt(curl, CURLOPT_INFILESIZE, buf.st_size); + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)buf.st_size); /* everything is done here; result 0 means success */ result = curl_easy_perform(curl); /* goodbye */ diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index dd992aa..cd45493 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -307,7 +307,7 @@ static void DeleteFileDir(const char *pDir) } } closedir(dir); - if (remove(pDir) == -1) + if (rmdir(pDir) == -1) { throw CABRTException(EXCEP_DD_DELETE, "Can't remove dir %s", pDir); } diff --git a/lib/Utils/abrt_dbus.h b/lib/Utils/abrt_dbus.h index bc9889a..25e099e 100644 --- a/lib/Utils/abrt_dbus.h +++ b/lib/Utils/abrt_dbus.h @@ -154,6 +154,9 @@ enum { ABRT_DBUS_ERROR = -1, ABRT_DBUS_LAST_FIELD = 0, ABRT_DBUS_MORE_FIELDS = 1, + /* note that dbus_message_iter_next() returns FALSE on last field + * and TRUE if there are more fields. + * It maps exactly on the above constants. */ }; /* Checks type, loads data, advances to the next arg. * Returns TRUE if next arg exists. diff --git a/lib/Utils/spawn.cpp b/lib/Utils/spawn.cpp index 4b0eecb..3aeb682 100644 --- a/lib/Utils/spawn.cpp +++ b/lib/Utils/spawn.cpp @@ -27,6 +27,7 @@ pid_t fork_execv_on_steroids(int flags, if (flags & EXECFLG_OUTPUT) xpipe(pipe_fm_child); + fflush(NULL); child = fork(); if (child == -1) { perror_msg_and_die("fork"); diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index 7ffbb2d..f360d33 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -158,8 +158,8 @@ char* xvasprintf(const char *format, va_list p) #else // Bloat for systems that haven't got the GNU extension. va_list p2; - r = vsnprintf(NULL, 0, format, p); va_copy(p2, p); + r = vsnprintf(NULL, 0, format, p); string_ptr = xmalloc(r+1); r = vsnprintf(string_ptr, r+1, format, p2); va_end(p2); @@ -374,7 +374,7 @@ void xsetreuid(uid_t ruid, uid_t euid) perror_msg_and_die("can't set %cid %lu", 'u', (long)ruid); } -void xsetregid(gid_t rgid, uid_t egid) +void xsetregid(gid_t rgid, gid_t egid) { if (setregid(rgid, egid) != 0) perror_msg_and_die("can't set %cid %lu", 'g', (long)rgid); diff --git a/src/Applet/CCApplet.cpp b/src/Applet/CCApplet.cpp index 770915a..302fe0b 100644 --- a/src/Applet/CCApplet.cpp +++ b/src/Applet/CCApplet.cpp @@ -192,20 +192,21 @@ void CApplet::SetIconTooltip(const char *format, ...) void CApplet::CrashNotify(const char *format, ...) { va_list args; - char *buf; - int n; - GError *err = NULL; va_start(args, format); - buf = NULL; - n = vasprintf(&buf, format, args); + char *buf = xvasprintf(format, args); va_end(args); notify_notification_update(m_pNotification, _("Warning"), buf, NULL); + + GError *err = NULL; if (gtk_status_icon_is_embedded(m_pStatusIcon)) notify_notification_show(m_pNotification, &err); if (err != NULL) + { error_msg("%s", err->message); + g_error_free(err); + } } void CApplet::OnAppletActivate_CB(GtkStatusIcon *status_icon, gpointer user_data) diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 9e1aa0d..0f9c622 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -203,10 +203,12 @@ static int SetUpCron() int nM = -1; int nS = -1; +//TODO: rewrite using good old sscanf? + if (pos != std::string::npos) { - std::string sH = ""; - std::string sM = ""; + std::string sH; + std::string sM; sH = it_c->first.substr(0, pos); nH = xatou(sH.c_str()); @@ -221,7 +223,7 @@ static int SetUpCron() } else { - std::string sS = ""; + std::string sS; sS = it_c->first; nS = xatou(sS.c_str()); diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 3656060..a348a92 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -548,6 +548,8 @@ report_status_t Report(const map_crash_report_t& pCrashReport, static bool IsDebugDumpSaved(const char *pUID, const char *pDebugDumpDir) { + /* TODO: use database query instead of dumping all rows and searching in them */ + CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase.c_str()); database->Connect(); vector_database_rows_t rows = database->GetUIDData(pUID); diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 697b964..a6550e7 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -138,6 +138,8 @@ void CPluginManager::LoadPlugins() if (!ext || strcmp(ext + 1, PLUGINS_LIB_EXTENSION) != 0) continue; *ext = '\0'; + if (strncmp(dent->d_name, PLUGINS_LIB_PREFIX, sizeof(PLUGINS_LIB_PREFIX)-1) != 0) + continue; LoadPlugin(dent->d_name + sizeof(PLUGINS_LIB_PREFIX)-1, /*enabled_only:*/ true); } closedir(dir); diff --git a/src/Daemon/RPM.cpp b/src/Daemon/RPM.cpp index 6f05c0b..6cc0ba6 100644 --- a/src/Daemon/RPM.cpp +++ b/src/Daemon/RPM.cpp @@ -4,8 +4,8 @@ CRPM::CRPM() { - char *argv[] = { (char*)"" }; - m_poptContext = rpmcliInit(0, argv, NULL); + static const char *const argv[] = { "", NULL }; + m_poptContext = rpmcliInit(1, (char**)argv, NULL); } CRPM::~CRPM() diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index b5bfff7..ea08bae 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -139,7 +139,7 @@ int main(int argc, char** argv) * if they happen too often. Else, write new marker value. */ snprintf(path, sizeof(path), "%s/last-ccpp", dddir); - fd = open(path, O_RDWR | O_CREAT, 0666); + fd = open(path, O_RDWR | O_CREAT, 0600); if (fd >= 0) { int sz; diff --git a/src/Hooks/dumpoops.cpp b/src/Hooks/dumpoops.cpp index 4b6778d..01e65c4 100644 --- a/src/Hooks/dumpoops.cpp +++ b/src/Hooks/dumpoops.cpp @@ -83,6 +83,7 @@ int main(int argc, char **argv) void *handle; errno = 0; +//TODO: use it directly, not via dlopen? handle = dlopen(PLUGINS_LIB_DIR"/libKerneloopsScanner.so", RTLD_NOW); if (!handle) perror_msg_and_die("can't load %s", PLUGINS_LIB_DIR"/libKerneloopsScanner.so"); -- cgit From 20645ae11a8a9a89cc712896b2f72a25bc62c8db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 12:12:53 +0100 Subject: DebugDump: more consistent logic in setting mode and uid:gid on dump dir With comments! yay. Before it, too restrictive mode was preventing python craches to be handled. Signed-off-by: Karel Klic Signed-off-by: Denys Vlasenko --- lib/Plugins/CCpp.cpp | 2 ++ lib/Utils/DebugDump.cpp | 71 ++++++++++++++++++++++++++++++++++++------------- lib/Utils/DebugDump.h | 2 ++ lib/Utils/spawn.cpp | 14 ++++++++++ src/Hooks/CCpp.cpp | 4 +++ 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 4bf1bc1..8b0c2b8 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -520,6 +520,8 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) { log(_("Getting global universal unique identification...")); +//TODO: convert to fork_execv_on_steroids(), nuke static concat_str_vector + string backtrace_path = concat_path_file(pDebugDumpDir, FILENAME_BACKTRACE); string executable; string package; diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index cd45493..3c00bb7 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -65,7 +65,9 @@ CDebugDump::CDebugDump() : m_sDebugDumpDir(""), m_pGetNextFileDir(NULL), m_bOpened(false), - m_bLocked(false) + m_bLocked(false), + m_uid(0), + m_gid(0) {} CDebugDump::~CDebugDump() @@ -97,6 +99,15 @@ void CDebugDump::Open(const char *pDir) } 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) @@ -236,6 +247,23 @@ void CDebugDump::UnLock() } } +/* 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. + * + * 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 uid:abrt + * + * Currently, we set dir's uid to uid parameter, but we do not allow + * write acces to the owner; and we set gid to abrt's group id + * and we give write access to _group_. + */ void CDebugDump::Create(const char *pDir, uid_t uid) { if (m_bOpened) @@ -256,26 +284,32 @@ void CDebugDump::Create(const char *pDir, uid_t uid) * any file in the directory, changing security-sensitive data * (e.g. "uid", "analyzer", "executable") */ - if (mkdir(m_sDebugDumpDir.c_str(), 0500) == -1) + if (mkdir(m_sDebugDumpDir.c_str(), 0570) == -1) { UnLock(); m_bOpened = false; throw CABRTException(EXCEP_DD_OPEN, "Can't create dir '%s'", pDir); } - /* paranoia? mkdir should have done it already */ - if (chmod(m_sDebugDumpDir.c_str(), 0500) == -1) +#if 0 + /* paranoia. mkdir did it already */ + if (chmod(m_sDebugDumpDir.c_str(), 0570) == -1) { UnLock(); m_bOpened = false; throw CABRTException(EXCEP_DD_OPEN, "Can't change mode of '%s'", pDir); } - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - if (chown(m_sDebugDumpDir.c_str(), uid, gid) == -1) +#endif + + m_uid = uid; + m_gid = 0; + struct group *gr = getgrnam("abrt"); + if (gr) + m_gid = gr->gr_gid; + else + error_msg("Group 'abrt' does not exist, using gid 0"); + if (chown(m_sDebugDumpDir.c_str(), m_uid, m_gid) == -1) { - /* if /var/cache/abrt is writable by all, _aborting_ here is not useful */ - /* let's just warn */ - perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(), (long)uid, (long)gid); + perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(), (long)m_uid, (long)m_gid); } SaveText(FILENAME_UID, to_string(uid).c_str()); @@ -372,18 +406,19 @@ static void LoadTextFile(const char *pPath, std::string& pData) fclose(fp); } -static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize) +static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize, uid_t uid, gid_t gid) { - /* Was creating it with mode 0666, but this allows the user to replace - * file's contents, changing security-sensitive data - * (e.g. "uid", "analyzer", "executable") - */ + /* "Why 0460?!" See ::Create() for security analysis */ unlink(pPath); - int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0444); + int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0460); if (fd < 0) { throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s'", pPath); } + 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) @@ -409,7 +444,7 @@ void CDebugDump::SaveText(const char* pName, const char* pData) 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)); + SaveBinaryFile(fullPath.c_str(), pData, strlen(pData), m_uid, m_gid); } void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize) @@ -419,7 +454,7 @@ void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize 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); + SaveBinaryFile(fullPath.c_str(), pData, pSize, m_uid, m_gid); } void CDebugDump::InitGetNextFile() diff --git a/lib/Utils/DebugDump.h b/lib/Utils/DebugDump.h index ce515db..d3eebb4 100644 --- a/lib/Utils/DebugDump.h +++ b/lib/Utils/DebugDump.h @@ -51,6 +51,8 @@ class CDebugDump DIR* m_pGetNextFileDir; bool m_bOpened; bool m_bLocked; + uid_t m_uid; + gid_t m_gid; void SaveKernelArchitectureRelease(); diff --git a/lib/Utils/spawn.cpp b/lib/Utils/spawn.cpp index 3aeb682..d3e6ac6 100644 --- a/lib/Utils/spawn.cpp +++ b/lib/Utils/spawn.cpp @@ -5,6 +5,19 @@ */ #include "abrtlib.h" +using namespace std; + +static string concat_str_vector(char **strings) +{ + string result; + while (*strings) { + result += *strings++; + if (*strings) + result += ' '; + } + return result; +} + /* Returns pid */ pid_t fork_execv_on_steroids(int flags, char **argv, @@ -71,6 +84,7 @@ pid_t fork_execv_on_steroids(int flags, if (dir) xchdir(dir); + VERB1 log("Executing: %s", concat_str_vector(argv).c_str()); execvp(argv[0], argv); if (!(flags & EXECFLG_QUIET)) perror_msg("Can't execute '%s'", argv[0]); diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index ea08bae..21fe0be 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -216,6 +216,10 @@ int main(int argc, char** argv) dd.Close(); perror_msg_and_die("can't open '%s'", path); } +//TODO: chown to uid:abrt? +//Currently it is owned by 0:0 but is readable by anyone, so the owner +//of the crashed binary still can access it, as he has +//r-x access to the dump dir. core_size = copyfd_eof(STDIN_FILENO, core_fd); if (core_size < 0 || fsync(core_fd) != 0) { -- cgit From d037916adc56d384717ebd6b7a5963543febc170 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Mon, 11 Jan 2010 12:27:18 +0100 Subject: Catch and display ABRTException thrown by CDebugDump::Create --- src/Hooks/abrt-hook-python.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index 1a7eace..d7fca67 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -26,6 +26,7 @@ #include "abrtlib.h" #include "hooklib.h" #include "DebugDump.h" +#include "ABRTException.h" #if HAVE_CONFIG_H # include #endif @@ -108,7 +109,12 @@ int main(int argc, char** argv) snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s", (long)time(NULL), pid); CDebugDump dd; - dd.Create(path, geteuid()); + + try { + dd.Create(path, geteuid()); + } catch (CABRTException &e) { + error_msg_and_die("Error while creating debug dump: %s", e.what()); + } dd.SaveText(FILENAME_ANALYZER, "Python"); dd.SaveText(FILENAME_EXECUTABLE, executable); -- cgit From 4af592f48f98f54f96e9baeecf853cf1a67b9c86 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 15:21:23 +0100 Subject: CCpp: use our own sha1 implementation (less pain with nss libs) Signed-off-by: Denys Vlasenko --- lib/Plugins/CCpp.cpp | 32 ++++++- lib/Plugins/CCpp_sha1.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++++++ lib/Plugins/CCpp_sha1.h | 30 +++++++ lib/Plugins/Makefile.am | 2 +- 4 files changed, 274 insertions(+), 4 deletions(-) create mode 100644 lib/Plugins/CCpp_sha1.cpp create mode 100644 lib/Plugins/CCpp_sha1.h diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 8b0c2b8..6455f44 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -34,6 +34,8 @@ #include "CommLayerInner.h" #include "Polkit.h" +#include "CCpp_sha1.h" + using namespace std; #define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern" @@ -55,10 +57,13 @@ CAnalyzerCCpp::CAnalyzerCCpp() : static string CreateHash(const char *pInput) { string ret; - HASHContext* hc; - unsigned char hash[SHA1_LENGTH]; + char hash_str[SHA1_LENGTH*2 + 1]; unsigned int len; +#if 0 +{ + unsigned char hash[SHA1_LENGTH]; + HASHContext *hc; hc = HASH_Create(HASH_AlgSHA1); if (!hc) { @@ -69,7 +74,6 @@ static string CreateHash(const char *pInput) HASH_End(hc, hash, &len, sizeof(hash)); HASH_Destroy(hc); - char hash_str[SHA1_LENGTH*2 + 1]; char *d = hash_str; unsigned char *s = hash; while (len) @@ -80,6 +84,28 @@ static string CreateHash(const char *pInput) len--; } *d = '\0'; +//log("hash1:%s str:'%s'", hash_str, pInput); +} +#endif + + unsigned char hash2[SHA1_LENGTH]; + sha1_ctx_t sha1ctx; + sha1_begin(&sha1ctx); + sha1_hash(pInput, strlen(pInput), &sha1ctx); + sha1_end(hash2, &sha1ctx); + len = SHA1_LENGTH; + + char *d = hash_str; + unsigned char *s = hash2; + while (len) + { + *d++ = "0123456789abcdef"[*s >> 4]; + *d++ = "0123456789abcdef"[*s & 0xf]; + s++; + len--; + } + *d = '\0'; +//log("hash2:%s str:'%s'", hash_str, pInput); return hash_str; } diff --git a/lib/Plugins/CCpp_sha1.cpp b/lib/Plugins/CCpp_sha1.cpp new file mode 100644 index 0000000..86a9e83 --- /dev/null +++ b/lib/Plugins/CCpp_sha1.cpp @@ -0,0 +1,214 @@ +/* vi: set sw=4 ts=4: */ +/* + * Based on shasum from http://www.netsw.org/crypto/hash/ + * Majorly hacked up to use Dr Brian Gladman's sha1 code + * + * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * + * --------------------------------------------------------------------------- + * Issue Date: 10/11/2002 + * + * This is a byte oriented version of SHA1 that operates on arrays of bytes + * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor + * + * --------------------------------------------------------------------------- + */ +#include "abrtlib.h" +#include "CCpp_sha1.h" + +#if defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ +# define SHA1_BIG_ENDIAN 1 +# define SHA1_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __BIG_ENDIAN +# define SHA1_BIG_ENDIAN 1 +# define SHA1_LITTLE_ENDIAN 0 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define SHA1_BIG_ENDIAN 0 +# define SHA1_LITTLE_ENDIAN 1 +#else +# error "Can't determine endianness" +#endif + + +#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) +/* for sha512: */ +#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) +#if SHA1_LITTLE_ENDIAN +static inline uint64_t hton64(uint64_t v) +{ + return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); +} +#else +#define hton64(v) (v) +#endif +#define ntoh64(v) hton64(v) + +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +#if defined(__GNUC__) && __GNUC__ >= 2 +# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0) +#else +# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0) +#endif + + +/* Some arch headers have conflicting defines */ +#undef ch +#undef parity +#undef maj +#undef rnd + +static void sha1_process_block64(sha1_ctx_t *ctx) +{ + unsigned t; + uint32_t W[80], a, b, c, d, e; + const uint32_t *words = (uint32_t*) ctx->wbuffer; + + for (t = 0; t < 16; ++t) { + W[t] = ntohl(*words); + words++; + } + + for (/*t = 16*/; t < 80; ++t) { + uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; + W[t] = rotl32(T, 1); + } + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + +/* Reverse byte order in 32-bit words */ +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +/* A normal version as set out in the FIPS. This version uses */ +/* partial loop unrolling and is optimised for the Pentium 4 */ +#define rnd(f,k) \ + do { \ + uint32_t T = a; \ + a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \ + e = d; \ + d = c; \ + c = rotl32(b, 30); \ + b = T; \ + } while (0) + + for (t = 0; t < 20; ++t) + rnd(ch, 0x5a827999); + + for (/*t = 20*/; t < 40; ++t) + rnd(parity, 0x6ed9eba1); + + for (/*t = 40*/; t < 60; ++t) + rnd(maj, 0x8f1bbcdc); + + for (/*t = 60*/; t < 80; ++t) + rnd(parity, 0xca62c1d6); +#undef ch +#undef parity +#undef maj +#undef rnd + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; +} + +void sha1_begin(sha1_ctx_t *ctx) +{ + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; + ctx->total64 = 0; + ctx->process_block = sha1_process_block64; +} + +static const uint32_t init256[] = { + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19 +}; +static const uint32_t init512_lo[] = { + 0xf3bcc908, + 0x84caa73b, + 0xfe94f82b, + 0x5f1d36f1, + 0xade682d1, + 0x2b3e6c1f, + 0xfb41bd6b, + 0x137e2179 +}; + +/* Used also for sha256 */ +void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) +{ + unsigned in_buf = ctx->total64 & 63; + unsigned add = 64 - in_buf; + + ctx->total64 += len; + + while (len >= add) { /* transfer whole blocks while possible */ + memcpy(ctx->wbuffer + in_buf, buffer, add); + buffer = (const char *)buffer + add; + len -= add; + add = 64; + in_buf = 0; + ctx->process_block(ctx); + } + + memcpy(ctx->wbuffer + in_buf, buffer, len); +} + +/* Used also for sha256 */ +void sha1_end(void *resbuf, sha1_ctx_t *ctx) +{ + unsigned pad, in_buf; + + in_buf = ctx->total64 & 63; + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ + ctx->wbuffer[in_buf++] = 0x80; + + /* This loop iterates either once or twice, no more, no less */ + while (1) { + pad = 64 - in_buf; + memset(ctx->wbuffer + in_buf, 0, pad); + in_buf = 0; + /* Do we have enough space for the length count? */ + if (pad >= 8) { + /* Store the 64-bit counter of bits in the buffer in BE format */ + uint64_t t = ctx->total64 << 3; + t = hton64(t); + /* wbuffer is suitably aligned for this */ + *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; + } + ctx->process_block(ctx); + if (pad >= 8) + break; + } + + in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; + /* This way we do not impose alignment constraints on resbuf: */ + if (SHA1_LITTLE_ENDIAN) { + unsigned i; + for (i = 0; i < in_buf; ++i) + ctx->hash[i] = htonl(ctx->hash[i]); + } + memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); +} diff --git a/lib/Plugins/CCpp_sha1.h b/lib/Plugins/CCpp_sha1.h new file mode 100644 index 0000000..8aad822 --- /dev/null +++ b/lib/Plugins/CCpp_sha1.h @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * Based on shasum from http://www.netsw.org/crypto/hash/ + * Majorly hacked up to use Dr Brian Gladman's sha1 code + * + * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK. + * Copyright (C) 2003 Glenn L. McGrath + * Copyright (C) 2003 Erik Andersen + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * + * --------------------------------------------------------------------------- + * Issue Date: 10/11/2002 + * + * This is a byte oriented version of SHA1 that operates on arrays of bytes + * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor + * + * --------------------------------------------------------------------------- + */ + +typedef struct sha1_ctx_t { + uint32_t hash[8]; /* 5, +3 elements for sha256 */ + uint64_t total64; + uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ + void (*process_block)(struct sha1_ctx_t*); +} sha1_ctx_t; + +void sha1_begin(sha1_ctx_t *ctx); +void sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx); +void sha1_end(void *resbuf, sha1_ctx_t *ctx); diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index 2e5ee38..d70b024 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -51,7 +51,7 @@ install-data-hook: $(DESTDIR)/$(DEBUG_INFO_DIR) $(DESTDIR)$(sysconfdir)/abrt/plugins/Logger.conf # CCpp -libCCpp_la_SOURCES = CCpp.cpp CCpp.h +libCCpp_la_SOURCES = CCpp.cpp CCpp.h CCpp_sha1.cpp CCpp_sha1.h libCCpp_la_LDFLAGS = -avoid-version libCCpp_la_LIBADD = $(NSS_LIBS) libCCpp_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils \ -- cgit From fd761d18b02686b9a39e3fcf4882ca40a1b5c6a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 16:09:28 +0100 Subject: *: remove nss dependencies Signed-off-by: Denys Vlasenko --- abrt.spec | 3 +-- configure.ac | 2 +- lib/Plugins/CCpp.cpp | 13 ++++++------- lib/Plugins/CCpp_sha1.h | 2 ++ lib/Plugins/Makefile.am | 7 +++---- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/abrt.spec b/abrt.spec index 85038e6..01d509f 100644 --- a/abrt.spec +++ b/abrt.spec @@ -16,13 +16,12 @@ BuildRequires: curl-devel BuildRequires: rpm-devel >= 4.6 BuildRequires: sqlite-devel > 3.0 BuildRequires: desktop-file-utils -BuildRequires: nss-devel +#BuildRequires: nss-devel BuildRequires: libnotify-devel BuildRequires: xmlrpc-c-devel BuildRequires: file-devel BuildRequires: python-devel BuildRequires: gettext -BuildRequires: nss-devel BuildRequires: polkit-devel BuildRequires: libzip-devel, libtar-devel, bzip2-devel, zlib-devel BuildRequires: intltool diff --git a/configure.ac b/configure.ac index 5c10a3f..4f73d07 100644 --- a/configure.ac +++ b/configure.ac @@ -39,7 +39,7 @@ PKG_CHECK_MODULES([DBUS], [dbus-1]) PKG_CHECK_MODULES([RPM], [rpm]) PKG_CHECK_MODULES([CURL], [libcurl]) PKG_CHECK_MODULES([LIBNOTIFY], [libnotify]) -PKG_CHECK_MODULES([NSS], [nss]) +#PKG_CHECK_MODULES([NSS], [nss]) PKG_CHECK_MODULES([XMLRPC], [xmlrpc]) PKG_CHECK_MODULES([XMLRPC_CLIENT], [xmlrpc_client]) PKG_CHECK_MODULES([POLKIT],[polkit-gobject-1]) diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 6455f44..6c200d0 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -24,9 +24,8 @@ #include #include #include -#include -#include -#include +//#include +//#include #include "abrtlib.h" #include "CCpp.h" #include "ABRTException.h" @@ -56,12 +55,11 @@ CAnalyzerCCpp::CAnalyzerCCpp() : static string CreateHash(const char *pInput) { - string ret; - char hash_str[SHA1_LENGTH*2 + 1]; unsigned int len; #if 0 { + char hash_str[SHA1_LENGTH*2 + 1]; unsigned char hash[SHA1_LENGTH]; HASHContext *hc; hc = HASH_Create(HASH_AlgSHA1); @@ -88,12 +86,13 @@ static string CreateHash(const char *pInput) } #endif - unsigned char hash2[SHA1_LENGTH]; + char hash_str[SHA1_RESULT_LEN*2 + 1]; + unsigned char hash2[SHA1_RESULT_LEN]; sha1_ctx_t sha1ctx; sha1_begin(&sha1ctx); sha1_hash(pInput, strlen(pInput), &sha1ctx); sha1_end(hash2, &sha1ctx); - len = SHA1_LENGTH; + len = SHA1_RESULT_LEN; char *d = hash_str; unsigned char *s = hash2; diff --git a/lib/Plugins/CCpp_sha1.h b/lib/Plugins/CCpp_sha1.h index 8aad822..abadfd9 100644 --- a/lib/Plugins/CCpp_sha1.h +++ b/lib/Plugins/CCpp_sha1.h @@ -18,6 +18,8 @@ * --------------------------------------------------------------------------- */ +#define SHA1_RESULT_LEN (5 * 4) + typedef struct sha1_ctx_t { uint32_t hash[8]; /* 5, +3 elements for sha256 */ uint64_t total64; diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index d70b024..f93f510 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -53,12 +53,11 @@ install-data-hook: $(DESTDIR)/$(DEBUG_INFO_DIR) # CCpp libCCpp_la_SOURCES = CCpp.cpp CCpp.h CCpp_sha1.cpp CCpp_sha1.h libCCpp_la_LDFLAGS = -avoid-version -libCCpp_la_LIBADD = $(NSS_LIBS) +#libCCpp_la_LIBADD = libCCpp_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils \ -DCCPP_HOOK_PATH=\"${libexecdir}/abrt-hook-ccpp\" \ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ - -DLOCALSTATEDIR='"$(localstatedir)"' \ - $(NSS_CFLAGS) + -DLOCALSTATEDIR='"$(localstatedir)"' # Firefox - disabled for now @@ -133,7 +132,7 @@ libTicketUploader_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils $(CUR libPython_la_SOURCES = Python.h Python.cpp #libPython_la_LIBADD = $(NSS_LIBS) libPython_la_LDFLAGS = -avoid-version -libPython_la_CPPFLAGS = $(NSS_CFLAGS) -I$(srcdir)/../../inc -I$(srcdir)/../Utils +libPython_la_CPPFLAGS = -I$(srcdir)/../../inc -I$(srcdir)/../Utils # FileTrasfer libFileTransfer_la_SOURCES = FileTransfer.cpp FileTransfer.h -- cgit From 763b311bbfec96404f1d555347a33a1fad7f8995 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Jan 2010 16:17:34 +0100 Subject: Kerneloops: we require commandline for every crash, save dummy one for oopses Signed-off-by: Denys Vlasenko --- lib/Plugins/KerneloopsScanner.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp index f05f0d8..2d4499f 100644 --- a/lib/Plugins/KerneloopsScanner.cpp +++ b/lib/Plugins/KerneloopsScanner.cpp @@ -99,13 +99,14 @@ void CKerneloopsScanner::SaveOopsToDebugDump() *second_line++ = '\0'; try { - CDebugDump debugDump; - debugDump.Create(path, 0); - debugDump.SaveText(FILENAME_ANALYZER, "Kerneloops"); - debugDump.SaveText(FILENAME_EXECUTABLE, "kernel"); - debugDump.SaveText(FILENAME_KERNEL, first_line); - debugDump.SaveText(FILENAME_PACKAGE, "not_applicable"); - debugDump.SaveText(FILENAME_KERNELOOPS, second_line); + CDebugDump dd; + dd.Create(path, 0); + dd.SaveText(FILENAME_ANALYZER, "Kerneloops"); + dd.SaveText(FILENAME_EXECUTABLE, "kernel"); + dd.SaveText(FILENAME_KERNEL, first_line); + dd.SaveText(FILENAME_PACKAGE, "not_applicable"); + dd.SaveText(FILENAME_CMDLINE, "not_applicable"); + dd.SaveText(FILENAME_KERNELOOPS, second_line); } catch (CABRTException& e) { -- cgit From 71fb2d7e690640b391b76b5432f07b4a81351c8b Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Tue, 12 Jan 2010 14:26:08 +0100 Subject: Fixing /var/cache/abrt/ permissions by allowing users to read, but not to change their crash data. Adds abrt user, changes abrt-hook-python to use suid instead of sgid bit (uid=abrt), sets /var/cache/abrt and every dump subdirectory to be owned by abrt user. Read access for users and their own crashes is provided by group (/var/cache/abrt/ccpp-xxxx-xx has user's group). --- abrt.spec | 5 +++-- lib/Utils/DebugDump.cpp | 51 +++++++++++++++++++++++++----------------- src/Daemon/Daemon.cpp | 14 ++++++------ src/Hooks/abrt-hook-python.cpp | 2 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/abrt.spec b/abrt.spec index 85038e6..630e54c 100644 --- a/abrt.spec +++ b/abrt.spec @@ -250,6 +250,7 @@ rm -rf $RPM_BUILD_ROOT %pre getent group abrt >/dev/null || groupadd -f --system abrt +getent passwd abrt >/dev/null || useradd --system -g abrt -d /etc/abrt -s /sbin/nologin abrt exit 0 %post @@ -279,7 +280,7 @@ fi %config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf %config(noreplace) %{_sysconfdir}/dbus-1/system.d/dbus-%{name}.conf %{_initrddir}/%{name}d -%dir %attr(0775, root, abrt) %{_localstatedir}/cache/%{name} +%dir %attr(0755, abrt, abrt) %{_localstatedir}/cache/%{name} %dir /var/run/%{name} %dir %{_sysconfdir}/%{name} %dir %{_sysconfdir}/%{name}/plugins @@ -386,7 +387,7 @@ fi %files addon-python %defattr(-,root,root,-) -%attr(2755, root, abrt) %{_libexecdir}/abrt-hook-python +%attr(4755, abrt, abrt) %{_libexecdir}/abrt-hook-python %{_libdir}/%{name}/libPython.so* %{python_site}/*.py* diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp index 3c00bb7..a0a52ab 100644 --- a/lib/Utils/DebugDump.cpp +++ b/lib/Utils/DebugDump.cpp @@ -251,6 +251,9 @@ void CDebugDump::UnLock() * * 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 @@ -258,11 +261,10 @@ void CDebugDump::UnLock() * 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 uid:abrt + * this hook runs under abrt:gid * - * Currently, we set dir's uid to uid parameter, but we do not allow - * write acces to the owner; and we set gid to abrt's group id - * and we give write access to _group_. + * 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) { @@ -280,36 +282,45 @@ void CDebugDump::Create(const char *pDir, uid_t uid) Lock(); m_bOpened = true; - /* Was creating it with mode 0700, but this allows the user to replace - * any file in the directory, changing security-sensitive data + /* 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(), 0570) == -1) + if (mkdir(m_sDebugDumpDir.c_str(), 0750) == -1) { UnLock(); m_bOpened = false; throw CABRTException(EXCEP_DD_OPEN, "Can't create dir '%s'", pDir); } -#if 0 - /* paranoia. mkdir did it already */ - if (chmod(m_sDebugDumpDir.c_str(), 0570) == -1) + + /* 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); } -#endif - m_uid = uid; + /* 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; - struct group *gr = getgrnam("abrt"); - if (gr) - m_gid = gr->gr_gid; + pw = getpwuid(uid); + if (pw) + m_gid = pw->pw_gid; else - error_msg("Group 'abrt' does not exist, using gid 0"); + 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); + perror_msg("can't change '%s' ownership to %lu:%lu", m_sDebugDumpDir.c_str(), + (long)m_uid, (long)m_gid); } SaveText(FILENAME_UID, to_string(uid).c_str()); @@ -408,12 +419,12 @@ static void LoadTextFile(const char *pPath, std::string& pData) static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize, uid_t uid, gid_t gid) { - /* "Why 0460?!" See ::Create() for security analysis */ + /* "Why 0640?!" See ::Create() for security analysis */ unlink(pPath); - int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0460); + int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0640); if (fd < 0) { - throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s'", pPath); + throw CABRTException(EXCEP_DD_SAVE, "Can't open file '%s': %s", pPath, errno ? strerror(errno) : "errno == 0"); } if (fchown(fd, uid, gid) == -1) { diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 0f9c622..09d8ab8 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -632,7 +632,7 @@ static void start_syslog_logging() logmode = LOGMODE_SYSLOG; } -static void ensure_writable_dir(const char *dir, mode_t mode, const char *group) +static void ensure_writable_dir(const char *dir, mode_t mode, const char *user) { struct stat sb; @@ -641,12 +641,12 @@ static void ensure_writable_dir(const char *dir, mode_t mode, const char *group) if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode)) error_msg_and_die("'%s' is not a directory", dir); - struct group *gr = getgrnam(group); - if (!gr) - perror_msg_and_die("Can't find group '%s'", group); + struct passwd *pw = getpwnam(user); + if (!pw) + perror_msg_and_die("Can't find user '%s'", user); - if ((sb.st_uid != 0 || sb.st_gid != gr->gr_gid) && chown(dir, 0, gr->gr_gid) != 0) - perror_msg_and_die("Can't set owner 0:%u on '%s'", (unsigned int)gr->gr_gid, dir); + if ((sb.st_uid != pw->pw_uid || sb.st_gid != pw->pw_gid) && chown(dir, pw->pw_uid, pw->pw_gid) != 0) + perror_msg_and_die("Can't set owner %u:%u on '%s'", (unsigned int)pw->pw_uid, (unsigned int)pw->pw_gid, dir); if ((sb.st_mode & 07777) != mode && chmod(dir, mode) != 0) perror_msg_and_die("Can't set mode %o on '%s'", mode, dir); } @@ -657,7 +657,7 @@ static void sanitize_dump_dir_rights() * us with thousands of bogus or malicious dumps */ /* 07000 bits are setuid, setgit, and sticky, and they must be unset */ /* 00777 bits are usual "rwxrwxrwx" access rights */ - ensure_writable_dir(DEBUG_DUMPS_DIR, 0775, "abrt"); + ensure_writable_dir(DEBUG_DUMPS_DIR, 0755, "abrt"); /* debuginfo cache */ ensure_writable_dir(DEBUG_DUMPS_DIR"-di", 0755, "root"); /* temp dir */ diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index d7fca67..b921fba 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -111,7 +111,7 @@ int main(int argc, char** argv) CDebugDump dd; try { - dd.Create(path, geteuid()); + dd.Create(path, getuid()); } catch (CABRTException &e) { error_msg_and_die("Error while creating debug dump: %s", e.what()); } -- cgit From 223a6051757ac531d89c2a576da89b6b6f46ecf2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Jan 2010 16:30:40 +0100 Subject: src/Hooks/CCpp.cpp -> src/Hooks/abrt_hook_ccpp.cpp Signed-off-by: Denys Vlasenko --- lib/Plugins/Bugzilla.cpp | 4 +- src/Hooks/CCpp.cpp | 368 ------------------------------------------- src/Hooks/Makefile.am | 2 +- src/Hooks/abrt_hook_ccpp.cpp | 368 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 371 insertions(+), 371 deletions(-) delete mode 100644 src/Hooks/CCpp.cpp create mode 100644 src/Hooks/abrt_hook_ccpp.cpp diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp index 2d065f6..14eb87f 100644 --- a/lib/Plugins/Bugzilla.cpp +++ b/lib/Plugins/Bugzilla.cpp @@ -82,8 +82,8 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.getBug", param, &result); - throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(param); + throw_if_xml_fault_occurred(&env); xmlrpc_value* reporter_member = NULL; xmlrpc_struct_find_value(&env, result, "reporter", &reporter_member); @@ -298,9 +298,9 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra throw_if_xml_fault_occurred(&env); xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.addAttachment", param, &result); - throw_if_xml_fault_occurred(&env); xmlrpc_DECREF(result); xmlrpc_DECREF(param); + throw_if_xml_fault_occurred(&env); } } } diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp deleted file mode 100644 index 21fe0be..0000000 --- a/src/Hooks/CCpp.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - CCpp.cpp - the hook for C/C++ crashing program - - 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 "abrtlib.h" -#include "hooklib.h" -#include "DebugDump.h" -#include "ABRTException.h" -#include -#include - -#define FILENAME_EXECUTABLE "executable" -#define FILENAME_COREDUMP "coredump" - -using namespace std; - -static char* malloc_readlink(const char *linkname) -{ - char buf[PATH_MAX + 1]; - int len; - - len = readlink(linkname, buf, sizeof(buf)-1); - if (len >= 0) - { - buf[len] = '\0'; - return xstrdup(buf); - } - return NULL; -} - -static char* get_executable(pid_t pid) -{ - char buf[sizeof("/proc/%lu/exe") + sizeof(long)*3]; - - sprintf(buf, "/proc/%lu/exe", (long)pid); - return malloc_readlink(buf); -} - -static char* get_cwd(pid_t pid) -{ - char buf[sizeof("/proc/%lu/cwd") + sizeof(long)*3]; - - sprintf(buf, "/proc/%lu/cwd", (long)pid); - return malloc_readlink(buf); -} - -int main(int argc, char** argv) -{ - int fd; - struct stat sb; - - if (argc < 5) - { - const char* program_name = argv[0]; - error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); - } - openlog("abrt", 0, LOG_PID | LOG_DAEMON); - logmode = LOGMODE_SYSLOG; - - errno = 0; - const char* dddir = argv[1]; - pid_t pid = xatoi_u(argv[2]); - const char* signal_str = argv[3]; - int signal_no = xatoi_u(argv[3]); - uid_t uid = xatoi_u(argv[4]); - off_t ulimit_c = strtoull(argv[5], NULL, 10); - off_t core_size = 0; - - if (errno || pid <= 0 || ulimit_c < 0) - { - error_msg_and_die("pid '%s' or limit '%s' is bogus", argv[2], argv[5]); - } - if (signal_no != SIGQUIT - && signal_no != SIGILL - && signal_no != SIGABRT - && signal_no != SIGFPE - && signal_no != SIGSEGV - ) { - /* not an error, exit silently */ - return 0; - } - - - char *user_pwd = get_cwd(pid); /* may be NULL on error */ - int core_fd = STDIN_FILENO; - - if (!daemon_is_ok()) - { - /* not an error, exit with exitcode 0 */ - log("abrt daemon is not running. If it crashed, " - "/proc/sys/kernel/core_pattern contains a stale value, " - "consider resetting it to 'core'" - ); - goto create_user_core; - } - - try - { - char* executable = get_executable(pid); - if (executable == NULL) - { - error_msg_and_die("can't read /proc/%lu/exe link", (long)pid); - } - if (strstr(executable, "/abrt-hook-ccpp")) - { - error_msg_and_die("pid %lu is '%s', not dumping it to avoid recursion", - (long)pid, executable); - } - - /* Parse abrt.conf and plugins/CCpp.conf */ - unsigned setting_MaxCrashReportsSize = 0; - bool setting_MakeCompatCore = false; - parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore); - - if (setting_MaxCrashReportsSize > 0) - { - check_free_space(setting_MaxCrashReportsSize); - } - - char path[PATH_MAX]; - - /* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes - * if they happen too often. Else, write new marker value. - */ - snprintf(path, sizeof(path), "%s/last-ccpp", dddir); - fd = open(path, O_RDWR | O_CREAT, 0600); - if (fd >= 0) - { - int sz; - fstat(fd, &sb); /* !paranoia. this can't fail. */ - - if (sb.st_size != 0 /* if it wasn't created by us just now... */ - && (unsigned)(time(NULL) - sb.st_mtime) < 20 /* and is relatively new [is 20 sec ok?] */ - ) { - sz = read(fd, path, sizeof(path)-1); /* (ab)using path as scratch buf */ - if (sz > 0) - { - path[sz] = '\0'; - if (strcmp(executable, path) == 0) - { - error_msg("not dumping repeating crash in '%s'", executable); - if (setting_MakeCompatCore) - goto create_user_core; - return 1; - } - } - lseek(fd, 0, SEEK_SET); - } - sz = write(fd, executable, strlen(executable)); - if (sz >= 0) - ftruncate(fd, sz); - close(fd); - } - - if (strstr(executable, "/abrtd")) - { - /* If abrtd crashes, we don't want to create a _directory_, - * since that can make new copy of abrtd to process it, - * and maybe crash again... - * Unlike dirs, mere files are ignored by abrtd. - */ - snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir); - core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - core_size = copyfd_eof(STDIN_FILENO, core_fd); - if (core_size < 0 || close(core_fd) != 0) - { - unlink(path); - /* copyfd_eof logs the error including errno string, - * but it does not log file name */ - error_msg_and_die("error saving coredump to %s", path); - } - log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); - return 0; - } - - char* cmdline = get_cmdline(pid); /* never NULL */ - const char *signame = strsignal(signal_no); - char *reason = xasprintf("Process was terminated by signal %s (%s)", signal_str, signame ? signame : signal_str); - - snprintf(path, sizeof(path), "%s/ccpp-%ld-%lu", dddir, (long)time(NULL), (long)pid); - CDebugDump dd; - dd.Create(path, uid); - dd.SaveText(FILENAME_ANALYZER, "CCpp"); - dd.SaveText(FILENAME_EXECUTABLE, executable); - dd.SaveText(FILENAME_CMDLINE, cmdline); - dd.SaveText(FILENAME_REASON, reason); - - int len = strlen(path); - snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP); - - /* We need coredumps to be readable by all, because - * when abrt daemon processes coredump, - * process producing backtrace is run under the same UID - * as the crashed process. - * Thus 644, not 600 */ - core_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (core_fd < 0) - { - dd.Delete(); - dd.Close(); - perror_msg_and_die("can't open '%s'", path); - } -//TODO: chown to uid:abrt? -//Currently it is owned by 0:0 but is readable by anyone, so the owner -//of the crashed binary still can access it, as he has -//r-x access to the dump dir. - core_size = copyfd_eof(STDIN_FILENO, core_fd); - if (core_size < 0 || fsync(core_fd) != 0) - { - unlink(path); - dd.Delete(); - dd.Close(); - /* copyfd_eof logs the error including errno string, - * but it does not log file name */ - error_msg_and_die("error saving coredump to %s", path); - } - lseek(core_fd, 0, SEEK_SET); - /* note: core_fd is still open, we may use it later to copy core to user's dir */ - log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); - free(executable); - free(cmdline); - path[len] = '\0'; /* path now contains directory name */ - - /* We close dumpdir before we start catering for crash storm case. - * Otherwise, delete_debug_dump_dir's from other concurrent - * CCpp's won't be able to delete our dump (their delete_debug_dump_dir - * will wait for us), and we won't be able to delete their dumps. - * Classic deadlock. - */ - dd.Close(); - - /* rhbz#539551: "abrt going crazy when crashing process is respawned" */ - if (setting_MaxCrashReportsSize > 0) - { - trim_debug_dumps(setting_MaxCrashReportsSize, path); - } - - if (!setting_MakeCompatCore) - return 0; - /* fall through to creating user core */ - } - catch (CABRTException& e) - { - error_msg_and_die("%s", e.what()); - } - catch (std::exception& e) - { - error_msg_and_die("%s", e.what()); - } - - - create_user_core: - /* note: core_size may be == 0 ("unknown") */ - if (core_size > ulimit_c || ulimit_c == 0) - return 0; - - /* Write a core file for user */ - - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - setgroups(1, &gid); - xsetregid(gid, gid); - xsetreuid(uid, uid); - - errno = 0; - if (user_pwd == NULL - || chdir(user_pwd) != 0 - ) { - perror_msg_and_die("can't cd to %s", user_pwd); - } - - /* Mimic "core.PID" if requested */ - char core_basename[sizeof("core.%lu") + sizeof(long)*3] = "core"; - char buf[] = "0\n"; - fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY); - if (fd >= 0) - { - read(fd, buf, sizeof(buf)); - close(fd); - } - if (strcmp(buf, "1\n") == 0) - { - sprintf(core_basename, "core.%lu", (long)pid); - } - - /* man core: - * There are various circumstances in which a core dump file - * is not produced: - * - * [skipped obvious ones] - * The process does not have permission to write the core file. - * ...if a file with the same name exists and is not writable - * or is not a regular file (e.g., it is a directory or a symbolic link). - * - * A file with the same name already exists, but there is more - * than one hard link to that file. - * - * The file system where the core dump file would be created is full; - * or has run out of inodes; or is mounted read-only; - * or the user has reached their quota for the file system. - * - * The RLIMIT_CORE or RLIMIT_FSIZE resource limits for the process - * are set to zero. - * [shouldn't it be checked by kernel? 2.6.30.9-96 doesn't, still - * calls us even if "ulimit -c 0"] - * - * The binary being executed by the process does not have - * read permission enabled. [how we can check it here?] - * - * The process is executing a set-user-ID (set-group-ID) program - * that is owned by a user (group) other than the real - * user (group) ID of the process. [TODO?] - * (However, see the description of the prctl(2) PR_SET_DUMPABLE operation, - * and the description of the /proc/sys/fs/suid_dumpable file in proc(5).) - */ - - /* Do not O_TRUNC: if later checks fail, we do not want to have file already modified here */ - errno = 0; - int usercore_fd = open(core_basename, O_WRONLY | O_CREAT | O_NOFOLLOW, 0600); /* kernel makes 0600 too */ - if (usercore_fd < 0 - || fstat(usercore_fd, &sb) != 0 - || !S_ISREG(sb.st_mode) - || sb.st_nlink != 1 - /* kernel internal dumper checks this too: if (inode->i_uid != current->fsuid) , need to mimic? */ - ) { - perror_msg_and_die("%s/%s is not a regular file with link count 1", user_pwd, core_basename); - } - - /* Note: we do not copy more than ulimit_c */ - off_t size; - if (ftruncate(usercore_fd, 0) != 0 - || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0 - || close(usercore_fd) != 0 - ) { - /* perror first, otherwise unlink may trash errno */ - perror_msg("write error writing %s/%s", user_pwd, core_basename); - unlink(core_basename); - return 1; - } - if (size == ulimit_c && size != core_size) - { - /* We copied exactly ulimit_c bytes (and it doesn't accidentally match - * core_size (imagine exactly 1MB coredump with "ulimit -c 1M" - that'd be ok)), - * it means that core is larger than ulimit_c. Abort and delete the dump. - */ - unlink(core_basename); - return 1; - } - log("saved core dump of pid %lu to %s/%s (%llu bytes)", (long)pid, user_pwd, core_basename, (long long)size); - - return 0; -} diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am index ebabd87..d9c0fba 100644 --- a/src/Hooks/Makefile.am +++ b/src/Hooks/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = dumpoops # abrt-hook-ccpp abrt_hook_ccpp_SOURCES = \ - CCpp.cpp \ + abrt_hook_ccpp.cpp \ hooklib.h hooklib.cpp abrt_hook_ccpp_CPPFLAGS = \ -I$(srcdir)/../../inc \ diff --git a/src/Hooks/abrt_hook_ccpp.cpp b/src/Hooks/abrt_hook_ccpp.cpp new file mode 100644 index 0000000..e417743 --- /dev/null +++ b/src/Hooks/abrt_hook_ccpp.cpp @@ -0,0 +1,368 @@ +/* + abrt_hook_ccpp.cpp - the hook for C/C++ crashing program + + 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 "abrtlib.h" +#include "hooklib.h" +#include "DebugDump.h" +#include "ABRTException.h" +#include +#include + +#define FILENAME_EXECUTABLE "executable" +#define FILENAME_COREDUMP "coredump" + +using namespace std; + +static char* malloc_readlink(const char *linkname) +{ + char buf[PATH_MAX + 1]; + int len; + + len = readlink(linkname, buf, sizeof(buf)-1); + if (len >= 0) + { + buf[len] = '\0'; + return xstrdup(buf); + } + return NULL; +} + +static char* get_executable(pid_t pid) +{ + char buf[sizeof("/proc/%lu/exe") + sizeof(long)*3]; + + sprintf(buf, "/proc/%lu/exe", (long)pid); + return malloc_readlink(buf); +} + +static char* get_cwd(pid_t pid) +{ + char buf[sizeof("/proc/%lu/cwd") + sizeof(long)*3]; + + sprintf(buf, "/proc/%lu/cwd", (long)pid); + return malloc_readlink(buf); +} + +int main(int argc, char** argv) +{ + int fd; + struct stat sb; + + if (argc < 5) + { + const char* program_name = argv[0]; + error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); + } + openlog("abrt", 0, LOG_PID | LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + + errno = 0; + const char* dddir = argv[1]; + pid_t pid = xatoi_u(argv[2]); + const char* signal_str = argv[3]; + int signal_no = xatoi_u(argv[3]); + uid_t uid = xatoi_u(argv[4]); + off_t ulimit_c = strtoull(argv[5], NULL, 10); + off_t core_size = 0; + + if (errno || pid <= 0 || ulimit_c < 0) + { + error_msg_and_die("pid '%s' or limit '%s' is bogus", argv[2], argv[5]); + } + if (signal_no != SIGQUIT + && signal_no != SIGILL + && signal_no != SIGABRT + && signal_no != SIGFPE + && signal_no != SIGSEGV + ) { + /* not an error, exit silently */ + return 0; + } + + + char *user_pwd = get_cwd(pid); /* may be NULL on error */ + int core_fd = STDIN_FILENO; + + if (!daemon_is_ok()) + { + /* not an error, exit with exitcode 0 */ + log("abrt daemon is not running. If it crashed, " + "/proc/sys/kernel/core_pattern contains a stale value, " + "consider resetting it to 'core'" + ); + goto create_user_core; + } + + try + { + char* executable = get_executable(pid); + if (executable == NULL) + { + error_msg_and_die("can't read /proc/%lu/exe link", (long)pid); + } + if (strstr(executable, "/abrt-hook-ccpp")) + { + error_msg_and_die("pid %lu is '%s', not dumping it to avoid recursion", + (long)pid, executable); + } + + /* Parse abrt.conf and plugins/CCpp.conf */ + unsigned setting_MaxCrashReportsSize = 0; + bool setting_MakeCompatCore = false; + parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore); + + if (setting_MaxCrashReportsSize > 0) + { + check_free_space(setting_MaxCrashReportsSize); + } + + char path[PATH_MAX]; + + /* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes + * if they happen too often. Else, write new marker value. + */ + snprintf(path, sizeof(path), "%s/last-ccpp", dddir); + fd = open(path, O_RDWR | O_CREAT, 0600); + if (fd >= 0) + { + int sz; + fstat(fd, &sb); /* !paranoia. this can't fail. */ + + if (sb.st_size != 0 /* if it wasn't created by us just now... */ + && (unsigned)(time(NULL) - sb.st_mtime) < 20 /* and is relatively new [is 20 sec ok?] */ + ) { + sz = read(fd, path, sizeof(path)-1); /* (ab)using path as scratch buf */ + if (sz > 0) + { + path[sz] = '\0'; + if (strcmp(executable, path) == 0) + { + error_msg("not dumping repeating crash in '%s'", executable); + if (setting_MakeCompatCore) + goto create_user_core; + return 1; + } + } + lseek(fd, 0, SEEK_SET); + } + sz = write(fd, executable, strlen(executable)); + if (sz >= 0) + ftruncate(fd, sz); + close(fd); + } + + if (strstr(executable, "/abrtd")) + { + /* If abrtd crashes, we don't want to create a _directory_, + * since that can make new copy of abrtd to process it, + * and maybe crash again... + * Unlike dirs, mere files are ignored by abrtd. + */ + snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir); + core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + core_size = copyfd_eof(STDIN_FILENO, core_fd); + if (core_size < 0 || close(core_fd) != 0) + { + unlink(path); + /* copyfd_eof logs the error including errno string, + * but it does not log file name */ + error_msg_and_die("error saving coredump to %s", path); + } + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); + return 0; + } + + char* cmdline = get_cmdline(pid); /* never NULL */ + const char *signame = strsignal(signal_no); + char *reason = xasprintf("Process was terminated by signal %s (%s)", signal_str, signame ? signame : signal_str); + + snprintf(path, sizeof(path), "%s/ccpp-%ld-%lu", dddir, (long)time(NULL), (long)pid); + CDebugDump dd; + dd.Create(path, uid); + dd.SaveText(FILENAME_ANALYZER, "CCpp"); + dd.SaveText(FILENAME_EXECUTABLE, executable); + dd.SaveText(FILENAME_CMDLINE, cmdline); + dd.SaveText(FILENAME_REASON, reason); + + int len = strlen(path); + snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP); + + /* We need coredumps to be readable by all, because + * when abrt daemon processes coredump, + * process producing backtrace is run under the same UID + * as the crashed process. + * Thus 644, not 600 */ + core_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (core_fd < 0) + { + dd.Delete(); + dd.Close(); + perror_msg_and_die("can't open '%s'", path); + } +//TODO: chown to uid:abrt? +//Currently it is owned by 0:0 but is readable by anyone, so the owner +//of the crashed binary still can access it, as he has +//r-x access to the dump dir. + core_size = copyfd_eof(STDIN_FILENO, core_fd); + if (core_size < 0 || fsync(core_fd) != 0) + { + unlink(path); + dd.Delete(); + dd.Close(); + /* copyfd_eof logs the error including errno string, + * but it does not log file name */ + error_msg_and_die("error saving coredump to %s", path); + } + lseek(core_fd, 0, SEEK_SET); + /* note: core_fd is still open, we may use it later to copy core to user's dir */ + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); + free(executable); + free(cmdline); + path[len] = '\0'; /* path now contains directory name */ + + /* We close dumpdir before we start catering for crash storm case. + * Otherwise, delete_debug_dump_dir's from other concurrent + * CCpp's won't be able to delete our dump (their delete_debug_dump_dir + * will wait for us), and we won't be able to delete their dumps. + * Classic deadlock. + */ + dd.Close(); + + /* rhbz#539551: "abrt going crazy when crashing process is respawned" */ + if (setting_MaxCrashReportsSize > 0) + { + trim_debug_dumps(setting_MaxCrashReportsSize, path); + } + + if (!setting_MakeCompatCore) + return 0; + /* fall through to creating user core */ + } + catch (CABRTException& e) + { + error_msg_and_die("%s", e.what()); + } + catch (std::exception& e) + { + error_msg_and_die("%s", e.what()); + } + + + create_user_core: + /* note: core_size may be == 0 ("unknown") */ + if (core_size > ulimit_c || ulimit_c == 0) + return 0; + + /* Write a core file for user */ + + struct passwd* pw = getpwuid(uid); + gid_t gid = pw ? pw->pw_gid : uid; + setgroups(1, &gid); + xsetregid(gid, gid); + xsetreuid(uid, uid); + + errno = 0; + if (user_pwd == NULL + || chdir(user_pwd) != 0 + ) { + perror_msg_and_die("can't cd to %s", user_pwd); + } + + /* Mimic "core.PID" if requested */ + char core_basename[sizeof("core.%lu") + sizeof(long)*3] = "core"; + char buf[] = "0\n"; + fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY); + if (fd >= 0) + { + read(fd, buf, sizeof(buf)); + close(fd); + } + if (strcmp(buf, "1\n") == 0) + { + sprintf(core_basename, "core.%lu", (long)pid); + } + + /* man core: + * There are various circumstances in which a core dump file + * is not produced: + * + * [skipped obvious ones] + * The process does not have permission to write the core file. + * ...if a file with the same name exists and is not writable + * or is not a regular file (e.g., it is a directory or a symbolic link). + * + * A file with the same name already exists, but there is more + * than one hard link to that file. + * + * The file system where the core dump file would be created is full; + * or has run out of inodes; or is mounted read-only; + * or the user has reached their quota for the file system. + * + * The RLIMIT_CORE or RLIMIT_FSIZE resource limits for the process + * are set to zero. + * [shouldn't it be checked by kernel? 2.6.30.9-96 doesn't, still + * calls us even if "ulimit -c 0"] + * + * The binary being executed by the process does not have + * read permission enabled. [how we can check it here?] + * + * The process is executing a set-user-ID (set-group-ID) program + * that is owned by a user (group) other than the real + * user (group) ID of the process. [TODO?] + * (However, see the description of the prctl(2) PR_SET_DUMPABLE operation, + * and the description of the /proc/sys/fs/suid_dumpable file in proc(5).) + */ + + /* Do not O_TRUNC: if later checks fail, we do not want to have file already modified here */ + errno = 0; + int usercore_fd = open(core_basename, O_WRONLY | O_CREAT | O_NOFOLLOW, 0600); /* kernel makes 0600 too */ + if (usercore_fd < 0 + || fstat(usercore_fd, &sb) != 0 + || !S_ISREG(sb.st_mode) + || sb.st_nlink != 1 + /* kernel internal dumper checks this too: if (inode->i_uid != current->fsuid) , need to mimic? */ + ) { + perror_msg_and_die("%s/%s is not a regular file with link count 1", user_pwd, core_basename); + } + + /* Note: we do not copy more than ulimit_c */ + off_t size; + if (ftruncate(usercore_fd, 0) != 0 + || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0 + || close(usercore_fd) != 0 + ) { + /* perror first, otherwise unlink may trash errno */ + perror_msg("write error writing %s/%s", user_pwd, core_basename); + unlink(core_basename); + return 1; + } + if (size == ulimit_c && size != core_size) + { + /* We copied exactly ulimit_c bytes (and it doesn't accidentally match + * core_size (imagine exactly 1MB coredump with "ulimit -c 1M" - that'd be ok)), + * it means that core is larger than ulimit_c. Abort and delete the dump. + */ + unlink(core_basename); + return 1; + } + log("saved core dump of pid %lu to %s/%s (%llu bytes)", (long)pid, user_pwd, core_basename, (long long)size); + + return 0; +} -- cgit From bb4ce908e5dcec73b4a0f1bce0d2e6d499228c3c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Jan 2010 16:34:48 +0100 Subject: grr... src/Hooks/abrt_hook_ccpp.cpp -> abrt-hook-ccpp.cpp Signed-off-by: Denys Vlasenko --- src/Hooks/Makefile.am | 2 +- src/Hooks/abrt-hook-ccpp.cpp | 368 +++++++++++++++++++++++++++++++++++++++++++ src/Hooks/abrt_hook_ccpp.cpp | 368 ------------------------------------------- 3 files changed, 369 insertions(+), 369 deletions(-) create mode 100644 src/Hooks/abrt-hook-ccpp.cpp delete mode 100644 src/Hooks/abrt_hook_ccpp.cpp diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am index d9c0fba..2b04990 100644 --- a/src/Hooks/Makefile.am +++ b/src/Hooks/Makefile.am @@ -3,7 +3,7 @@ bin_PROGRAMS = dumpoops # abrt-hook-ccpp abrt_hook_ccpp_SOURCES = \ - abrt_hook_ccpp.cpp \ + abrt-hook-ccpp.cpp \ hooklib.h hooklib.cpp abrt_hook_ccpp_CPPFLAGS = \ -I$(srcdir)/../../inc \ diff --git a/src/Hooks/abrt-hook-ccpp.cpp b/src/Hooks/abrt-hook-ccpp.cpp new file mode 100644 index 0000000..237ea6f --- /dev/null +++ b/src/Hooks/abrt-hook-ccpp.cpp @@ -0,0 +1,368 @@ +/* + abrt-hook-ccpp.cpp - the hook for C/C++ crashing program + + 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 "abrtlib.h" +#include "hooklib.h" +#include "DebugDump.h" +#include "ABRTException.h" +#include +#include + +#define FILENAME_EXECUTABLE "executable" +#define FILENAME_COREDUMP "coredump" + +using namespace std; + +static char* malloc_readlink(const char *linkname) +{ + char buf[PATH_MAX + 1]; + int len; + + len = readlink(linkname, buf, sizeof(buf)-1); + if (len >= 0) + { + buf[len] = '\0'; + return xstrdup(buf); + } + return NULL; +} + +static char* get_executable(pid_t pid) +{ + char buf[sizeof("/proc/%lu/exe") + sizeof(long)*3]; + + sprintf(buf, "/proc/%lu/exe", (long)pid); + return malloc_readlink(buf); +} + +static char* get_cwd(pid_t pid) +{ + char buf[sizeof("/proc/%lu/cwd") + sizeof(long)*3]; + + sprintf(buf, "/proc/%lu/cwd", (long)pid); + return malloc_readlink(buf); +} + +int main(int argc, char** argv) +{ + int fd; + struct stat sb; + + if (argc < 5) + { + const char* program_name = argv[0]; + error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); + } + openlog("abrt", 0, LOG_PID | LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + + errno = 0; + const char* dddir = argv[1]; + pid_t pid = xatoi_u(argv[2]); + const char* signal_str = argv[3]; + int signal_no = xatoi_u(argv[3]); + uid_t uid = xatoi_u(argv[4]); + off_t ulimit_c = strtoull(argv[5], NULL, 10); + off_t core_size = 0; + + if (errno || pid <= 0 || ulimit_c < 0) + { + error_msg_and_die("pid '%s' or limit '%s' is bogus", argv[2], argv[5]); + } + if (signal_no != SIGQUIT + && signal_no != SIGILL + && signal_no != SIGABRT + && signal_no != SIGFPE + && signal_no != SIGSEGV + ) { + /* not an error, exit silently */ + return 0; + } + + + char *user_pwd = get_cwd(pid); /* may be NULL on error */ + int core_fd = STDIN_FILENO; + + if (!daemon_is_ok()) + { + /* not an error, exit with exitcode 0 */ + log("abrt daemon is not running. If it crashed, " + "/proc/sys/kernel/core_pattern contains a stale value, " + "consider resetting it to 'core'" + ); + goto create_user_core; + } + + try + { + char* executable = get_executable(pid); + if (executable == NULL) + { + error_msg_and_die("can't read /proc/%lu/exe link", (long)pid); + } + if (strstr(executable, "/abrt-hook-ccpp")) + { + error_msg_and_die("pid %lu is '%s', not dumping it to avoid recursion", + (long)pid, executable); + } + + /* Parse abrt.conf and plugins/CCpp.conf */ + unsigned setting_MaxCrashReportsSize = 0; + bool setting_MakeCompatCore = false; + parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore); + + if (setting_MaxCrashReportsSize > 0) + { + check_free_space(setting_MaxCrashReportsSize); + } + + char path[PATH_MAX]; + + /* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes + * if they happen too often. Else, write new marker value. + */ + snprintf(path, sizeof(path), "%s/last-ccpp", dddir); + fd = open(path, O_RDWR | O_CREAT, 0600); + if (fd >= 0) + { + int sz; + fstat(fd, &sb); /* !paranoia. this can't fail. */ + + if (sb.st_size != 0 /* if it wasn't created by us just now... */ + && (unsigned)(time(NULL) - sb.st_mtime) < 20 /* and is relatively new [is 20 sec ok?] */ + ) { + sz = read(fd, path, sizeof(path)-1); /* (ab)using path as scratch buf */ + if (sz > 0) + { + path[sz] = '\0'; + if (strcmp(executable, path) == 0) + { + error_msg("not dumping repeating crash in '%s'", executable); + if (setting_MakeCompatCore) + goto create_user_core; + return 1; + } + } + lseek(fd, 0, SEEK_SET); + } + sz = write(fd, executable, strlen(executable)); + if (sz >= 0) + ftruncate(fd, sz); + close(fd); + } + + if (strstr(executable, "/abrtd")) + { + /* If abrtd crashes, we don't want to create a _directory_, + * since that can make new copy of abrtd to process it, + * and maybe crash again... + * Unlike dirs, mere files are ignored by abrtd. + */ + snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir); + core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + core_size = copyfd_eof(STDIN_FILENO, core_fd); + if (core_size < 0 || close(core_fd) != 0) + { + unlink(path); + /* copyfd_eof logs the error including errno string, + * but it does not log file name */ + error_msg_and_die("error saving coredump to %s", path); + } + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); + return 0; + } + + char* cmdline = get_cmdline(pid); /* never NULL */ + const char *signame = strsignal(signal_no); + char *reason = xasprintf("Process was terminated by signal %s (%s)", signal_str, signame ? signame : signal_str); + + snprintf(path, sizeof(path), "%s/ccpp-%ld-%lu", dddir, (long)time(NULL), (long)pid); + CDebugDump dd; + dd.Create(path, uid); + dd.SaveText(FILENAME_ANALYZER, "CCpp"); + dd.SaveText(FILENAME_EXECUTABLE, executable); + dd.SaveText(FILENAME_CMDLINE, cmdline); + dd.SaveText(FILENAME_REASON, reason); + + int len = strlen(path); + snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP); + + /* We need coredumps to be readable by all, because + * when abrt daemon processes coredump, + * process producing backtrace is run under the same UID + * as the crashed process. + * Thus 644, not 600 */ + core_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (core_fd < 0) + { + dd.Delete(); + dd.Close(); + perror_msg_and_die("can't open '%s'", path); + } +//TODO: chown to uid:abrt? +//Currently it is owned by 0:0 but is readable by anyone, so the owner +//of the crashed binary still can access it, as he has +//r-x access to the dump dir. + core_size = copyfd_eof(STDIN_FILENO, core_fd); + if (core_size < 0 || fsync(core_fd) != 0) + { + unlink(path); + dd.Delete(); + dd.Close(); + /* copyfd_eof logs the error including errno string, + * but it does not log file name */ + error_msg_and_die("error saving coredump to %s", path); + } + lseek(core_fd, 0, SEEK_SET); + /* note: core_fd is still open, we may use it later to copy core to user's dir */ + log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); + free(executable); + free(cmdline); + path[len] = '\0'; /* path now contains directory name */ + + /* We close dumpdir before we start catering for crash storm case. + * Otherwise, delete_debug_dump_dir's from other concurrent + * CCpp's won't be able to delete our dump (their delete_debug_dump_dir + * will wait for us), and we won't be able to delete their dumps. + * Classic deadlock. + */ + dd.Close(); + + /* rhbz#539551: "abrt going crazy when crashing process is respawned" */ + if (setting_MaxCrashReportsSize > 0) + { + trim_debug_dumps(setting_MaxCrashReportsSize, path); + } + + if (!setting_MakeCompatCore) + return 0; + /* fall through to creating user core */ + } + catch (CABRTException& e) + { + error_msg_and_die("%s", e.what()); + } + catch (std::exception& e) + { + error_msg_and_die("%s", e.what()); + } + + + create_user_core: + /* note: core_size may be == 0 ("unknown") */ + if (core_size > ulimit_c || ulimit_c == 0) + return 0; + + /* Write a core file for user */ + + struct passwd* pw = getpwuid(uid); + gid_t gid = pw ? pw->pw_gid : uid; + setgroups(1, &gid); + xsetregid(gid, gid); + xsetreuid(uid, uid); + + errno = 0; + if (user_pwd == NULL + || chdir(user_pwd) != 0 + ) { + perror_msg_and_die("can't cd to %s", user_pwd); + } + + /* Mimic "core.PID" if requested */ + char core_basename[sizeof("core.%lu") + sizeof(long)*3] = "core"; + char buf[] = "0\n"; + fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY); + if (fd >= 0) + { + read(fd, buf, sizeof(buf)); + close(fd); + } + if (strcmp(buf, "1\n") == 0) + { + sprintf(core_basename, "core.%lu", (long)pid); + } + + /* man core: + * There are various circumstances in which a core dump file + * is not produced: + * + * [skipped obvious ones] + * The process does not have permission to write the core file. + * ...if a file with the same name exists and is not writable + * or is not a regular file (e.g., it is a directory or a symbolic link). + * + * A file with the same name already exists, but there is more + * than one hard link to that file. + * + * The file system where the core dump file would be created is full; + * or has run out of inodes; or is mounted read-only; + * or the user has reached their quota for the file system. + * + * The RLIMIT_CORE or RLIMIT_FSIZE resource limits for the process + * are set to zero. + * [shouldn't it be checked by kernel? 2.6.30.9-96 doesn't, still + * calls us even if "ulimit -c 0"] + * + * The binary being executed by the process does not have + * read permission enabled. [how we can check it here?] + * + * The process is executing a set-user-ID (set-group-ID) program + * that is owned by a user (group) other than the real + * user (group) ID of the process. [TODO?] + * (However, see the description of the prctl(2) PR_SET_DUMPABLE operation, + * and the description of the /proc/sys/fs/suid_dumpable file in proc(5).) + */ + + /* Do not O_TRUNC: if later checks fail, we do not want to have file already modified here */ + errno = 0; + int usercore_fd = open(core_basename, O_WRONLY | O_CREAT | O_NOFOLLOW, 0600); /* kernel makes 0600 too */ + if (usercore_fd < 0 + || fstat(usercore_fd, &sb) != 0 + || !S_ISREG(sb.st_mode) + || sb.st_nlink != 1 + /* kernel internal dumper checks this too: if (inode->i_uid != current->fsuid) , need to mimic? */ + ) { + perror_msg_and_die("%s/%s is not a regular file with link count 1", user_pwd, core_basename); + } + + /* Note: we do not copy more than ulimit_c */ + off_t size; + if (ftruncate(usercore_fd, 0) != 0 + || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0 + || close(usercore_fd) != 0 + ) { + /* perror first, otherwise unlink may trash errno */ + perror_msg("write error writing %s/%s", user_pwd, core_basename); + unlink(core_basename); + return 1; + } + if (size == ulimit_c && size != core_size) + { + /* We copied exactly ulimit_c bytes (and it doesn't accidentally match + * core_size (imagine exactly 1MB coredump with "ulimit -c 1M" - that'd be ok)), + * it means that core is larger than ulimit_c. Abort and delete the dump. + */ + unlink(core_basename); + return 1; + } + log("saved core dump of pid %lu to %s/%s (%llu bytes)", (long)pid, user_pwd, core_basename, (long long)size); + + return 0; +} diff --git a/src/Hooks/abrt_hook_ccpp.cpp b/src/Hooks/abrt_hook_ccpp.cpp deleted file mode 100644 index e417743..0000000 --- a/src/Hooks/abrt_hook_ccpp.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - abrt_hook_ccpp.cpp - the hook for C/C++ crashing program - - 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 "abrtlib.h" -#include "hooklib.h" -#include "DebugDump.h" -#include "ABRTException.h" -#include -#include - -#define FILENAME_EXECUTABLE "executable" -#define FILENAME_COREDUMP "coredump" - -using namespace std; - -static char* malloc_readlink(const char *linkname) -{ - char buf[PATH_MAX + 1]; - int len; - - len = readlink(linkname, buf, sizeof(buf)-1); - if (len >= 0) - { - buf[len] = '\0'; - return xstrdup(buf); - } - return NULL; -} - -static char* get_executable(pid_t pid) -{ - char buf[sizeof("/proc/%lu/exe") + sizeof(long)*3]; - - sprintf(buf, "/proc/%lu/exe", (long)pid); - return malloc_readlink(buf); -} - -static char* get_cwd(pid_t pid) -{ - char buf[sizeof("/proc/%lu/cwd") + sizeof(long)*3]; - - sprintf(buf, "/proc/%lu/cwd", (long)pid); - return malloc_readlink(buf); -} - -int main(int argc, char** argv) -{ - int fd; - struct stat sb; - - if (argc < 5) - { - const char* program_name = argv[0]; - error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); - } - openlog("abrt", 0, LOG_PID | LOG_DAEMON); - logmode = LOGMODE_SYSLOG; - - errno = 0; - const char* dddir = argv[1]; - pid_t pid = xatoi_u(argv[2]); - const char* signal_str = argv[3]; - int signal_no = xatoi_u(argv[3]); - uid_t uid = xatoi_u(argv[4]); - off_t ulimit_c = strtoull(argv[5], NULL, 10); - off_t core_size = 0; - - if (errno || pid <= 0 || ulimit_c < 0) - { - error_msg_and_die("pid '%s' or limit '%s' is bogus", argv[2], argv[5]); - } - if (signal_no != SIGQUIT - && signal_no != SIGILL - && signal_no != SIGABRT - && signal_no != SIGFPE - && signal_no != SIGSEGV - ) { - /* not an error, exit silently */ - return 0; - } - - - char *user_pwd = get_cwd(pid); /* may be NULL on error */ - int core_fd = STDIN_FILENO; - - if (!daemon_is_ok()) - { - /* not an error, exit with exitcode 0 */ - log("abrt daemon is not running. If it crashed, " - "/proc/sys/kernel/core_pattern contains a stale value, " - "consider resetting it to 'core'" - ); - goto create_user_core; - } - - try - { - char* executable = get_executable(pid); - if (executable == NULL) - { - error_msg_and_die("can't read /proc/%lu/exe link", (long)pid); - } - if (strstr(executable, "/abrt-hook-ccpp")) - { - error_msg_and_die("pid %lu is '%s', not dumping it to avoid recursion", - (long)pid, executable); - } - - /* Parse abrt.conf and plugins/CCpp.conf */ - unsigned setting_MaxCrashReportsSize = 0; - bool setting_MakeCompatCore = false; - parse_conf(CONF_DIR"/plugins/CCpp.conf", &setting_MaxCrashReportsSize, &setting_MakeCompatCore); - - if (setting_MaxCrashReportsSize > 0) - { - check_free_space(setting_MaxCrashReportsSize); - } - - char path[PATH_MAX]; - - /* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes - * if they happen too often. Else, write new marker value. - */ - snprintf(path, sizeof(path), "%s/last-ccpp", dddir); - fd = open(path, O_RDWR | O_CREAT, 0600); - if (fd >= 0) - { - int sz; - fstat(fd, &sb); /* !paranoia. this can't fail. */ - - if (sb.st_size != 0 /* if it wasn't created by us just now... */ - && (unsigned)(time(NULL) - sb.st_mtime) < 20 /* and is relatively new [is 20 sec ok?] */ - ) { - sz = read(fd, path, sizeof(path)-1); /* (ab)using path as scratch buf */ - if (sz > 0) - { - path[sz] = '\0'; - if (strcmp(executable, path) == 0) - { - error_msg("not dumping repeating crash in '%s'", executable); - if (setting_MakeCompatCore) - goto create_user_core; - return 1; - } - } - lseek(fd, 0, SEEK_SET); - } - sz = write(fd, executable, strlen(executable)); - if (sz >= 0) - ftruncate(fd, sz); - close(fd); - } - - if (strstr(executable, "/abrtd")) - { - /* If abrtd crashes, we don't want to create a _directory_, - * since that can make new copy of abrtd to process it, - * and maybe crash again... - * Unlike dirs, mere files are ignored by abrtd. - */ - snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir); - core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - core_size = copyfd_eof(STDIN_FILENO, core_fd); - if (core_size < 0 || close(core_fd) != 0) - { - unlink(path); - /* copyfd_eof logs the error including errno string, - * but it does not log file name */ - error_msg_and_die("error saving coredump to %s", path); - } - log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); - return 0; - } - - char* cmdline = get_cmdline(pid); /* never NULL */ - const char *signame = strsignal(signal_no); - char *reason = xasprintf("Process was terminated by signal %s (%s)", signal_str, signame ? signame : signal_str); - - snprintf(path, sizeof(path), "%s/ccpp-%ld-%lu", dddir, (long)time(NULL), (long)pid); - CDebugDump dd; - dd.Create(path, uid); - dd.SaveText(FILENAME_ANALYZER, "CCpp"); - dd.SaveText(FILENAME_EXECUTABLE, executable); - dd.SaveText(FILENAME_CMDLINE, cmdline); - dd.SaveText(FILENAME_REASON, reason); - - int len = strlen(path); - snprintf(path + len, sizeof(path) - len, "/"FILENAME_COREDUMP); - - /* We need coredumps to be readable by all, because - * when abrt daemon processes coredump, - * process producing backtrace is run under the same UID - * as the crashed process. - * Thus 644, not 600 */ - core_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); - if (core_fd < 0) - { - dd.Delete(); - dd.Close(); - perror_msg_and_die("can't open '%s'", path); - } -//TODO: chown to uid:abrt? -//Currently it is owned by 0:0 but is readable by anyone, so the owner -//of the crashed binary still can access it, as he has -//r-x access to the dump dir. - core_size = copyfd_eof(STDIN_FILENO, core_fd); - if (core_size < 0 || fsync(core_fd) != 0) - { - unlink(path); - dd.Delete(); - dd.Close(); - /* copyfd_eof logs the error including errno string, - * but it does not log file name */ - error_msg_and_die("error saving coredump to %s", path); - } - lseek(core_fd, 0, SEEK_SET); - /* note: core_fd is still open, we may use it later to copy core to user's dir */ - log("saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size); - free(executable); - free(cmdline); - path[len] = '\0'; /* path now contains directory name */ - - /* We close dumpdir before we start catering for crash storm case. - * Otherwise, delete_debug_dump_dir's from other concurrent - * CCpp's won't be able to delete our dump (their delete_debug_dump_dir - * will wait for us), and we won't be able to delete their dumps. - * Classic deadlock. - */ - dd.Close(); - - /* rhbz#539551: "abrt going crazy when crashing process is respawned" */ - if (setting_MaxCrashReportsSize > 0) - { - trim_debug_dumps(setting_MaxCrashReportsSize, path); - } - - if (!setting_MakeCompatCore) - return 0; - /* fall through to creating user core */ - } - catch (CABRTException& e) - { - error_msg_and_die("%s", e.what()); - } - catch (std::exception& e) - { - error_msg_and_die("%s", e.what()); - } - - - create_user_core: - /* note: core_size may be == 0 ("unknown") */ - if (core_size > ulimit_c || ulimit_c == 0) - return 0; - - /* Write a core file for user */ - - struct passwd* pw = getpwuid(uid); - gid_t gid = pw ? pw->pw_gid : uid; - setgroups(1, &gid); - xsetregid(gid, gid); - xsetreuid(uid, uid); - - errno = 0; - if (user_pwd == NULL - || chdir(user_pwd) != 0 - ) { - perror_msg_and_die("can't cd to %s", user_pwd); - } - - /* Mimic "core.PID" if requested */ - char core_basename[sizeof("core.%lu") + sizeof(long)*3] = "core"; - char buf[] = "0\n"; - fd = open("/proc/sys/kernel/core_uses_pid", O_RDONLY); - if (fd >= 0) - { - read(fd, buf, sizeof(buf)); - close(fd); - } - if (strcmp(buf, "1\n") == 0) - { - sprintf(core_basename, "core.%lu", (long)pid); - } - - /* man core: - * There are various circumstances in which a core dump file - * is not produced: - * - * [skipped obvious ones] - * The process does not have permission to write the core file. - * ...if a file with the same name exists and is not writable - * or is not a regular file (e.g., it is a directory or a symbolic link). - * - * A file with the same name already exists, but there is more - * than one hard link to that file. - * - * The file system where the core dump file would be created is full; - * or has run out of inodes; or is mounted read-only; - * or the user has reached their quota for the file system. - * - * The RLIMIT_CORE or RLIMIT_FSIZE resource limits for the process - * are set to zero. - * [shouldn't it be checked by kernel? 2.6.30.9-96 doesn't, still - * calls us even if "ulimit -c 0"] - * - * The binary being executed by the process does not have - * read permission enabled. [how we can check it here?] - * - * The process is executing a set-user-ID (set-group-ID) program - * that is owned by a user (group) other than the real - * user (group) ID of the process. [TODO?] - * (However, see the description of the prctl(2) PR_SET_DUMPABLE operation, - * and the description of the /proc/sys/fs/suid_dumpable file in proc(5).) - */ - - /* Do not O_TRUNC: if later checks fail, we do not want to have file already modified here */ - errno = 0; - int usercore_fd = open(core_basename, O_WRONLY | O_CREAT | O_NOFOLLOW, 0600); /* kernel makes 0600 too */ - if (usercore_fd < 0 - || fstat(usercore_fd, &sb) != 0 - || !S_ISREG(sb.st_mode) - || sb.st_nlink != 1 - /* kernel internal dumper checks this too: if (inode->i_uid != current->fsuid) , need to mimic? */ - ) { - perror_msg_and_die("%s/%s is not a regular file with link count 1", user_pwd, core_basename); - } - - /* Note: we do not copy more than ulimit_c */ - off_t size; - if (ftruncate(usercore_fd, 0) != 0 - || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0 - || close(usercore_fd) != 0 - ) { - /* perror first, otherwise unlink may trash errno */ - perror_msg("write error writing %s/%s", user_pwd, core_basename); - unlink(core_basename); - return 1; - } - if (size == ulimit_c && size != core_size) - { - /* We copied exactly ulimit_c bytes (and it doesn't accidentally match - * core_size (imagine exactly 1MB coredump with "ulimit -c 1M" - that'd be ok)), - * it means that core is larger than ulimit_c. Abort and delete the dump. - */ - unlink(core_basename); - return 1; - } - log("saved core dump of pid %lu to %s/%s (%llu bytes)", (long)pid, user_pwd, core_basename, (long long)size); - - return 0; -} -- cgit From b85dabbbf338c8e5f4813f3a04e298ce3a8b319f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 12 Jan 2010 17:07:01 +0100 Subject: abrt-hook-python: sanitize input more; log to syslog Signed-off-by: Denys Vlasenko --- src/Hooks/abrt-hook-ccpp.cpp | 3 +-- src/Hooks/abrt-hook-python.cpp | 53 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Hooks/abrt-hook-ccpp.cpp b/src/Hooks/abrt-hook-ccpp.cpp index 237ea6f..1c91dc8 100644 --- a/src/Hooks/abrt-hook-ccpp.cpp +++ b/src/Hooks/abrt-hook-ccpp.cpp @@ -23,7 +23,6 @@ #include "DebugDump.h" #include "ABRTException.h" #include -#include #define FILENAME_EXECUTABLE "executable" #define FILENAME_COREDUMP "coredump" @@ -70,7 +69,7 @@ int main(int argc, char** argv) const char* program_name = argv[0]; error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name); } - openlog("abrt", 0, LOG_PID | LOG_DAEMON); + openlog("abrt", LOG_PID, LOG_DAEMON); logmode = LOGMODE_SYSLOG; errno = 0; diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp index b921fba..c8a25e3 100644 --- a/src/Hooks/abrt-hook-python.cpp +++ b/src/Hooks/abrt-hook-python.cpp @@ -20,7 +20,7 @@ */ #include -#include +#include /* We can easily get rid of abrtlib (libABRTUtils.so) usage in this file, * but DebugDump will pull it in anyway */ #include "abrtlib.h" @@ -38,12 +38,33 @@ static char *pid; static char *executable; static char *uuid; -int main(int argc, char** argv) +/* Note: "" will return false */ +static bool isxdigit_str(const char *str) { - // Error if daemon is not running. - if (!daemon_is_ok()) - error_msg_and_die("Daemon is not running."); + do { + if ((*str < '0' || *str > '9') /* not a digit */ + && ((*str | 0x20) < 'a' || (*str | 0x20) > 'f') /* not A-F or a-f */ + ) + { + return false; + } + str++; + } while (*str); + return true; +} + +static bool printable_str(const char *str) +{ + do { + if ((unsigned char)(*str) < ' ' || *str == 0x7f) + return false; + str++; + } while (*str); + return true; +} +int main(int argc, char** argv) +{ // Parse options static const struct option longopts[] = { // name , has_arg , flag, val @@ -79,8 +100,18 @@ int main(int argc, char** argv) } if (!pid || !executable || !uuid) goto usage; + if (strlen(uuid) > 128 || !isxdigit_str(uuid)) + goto usage; + if (strlen(executable) > PATH_MAX || !printable_str(executable)) + goto usage; + // pid string is sanitized later by xatou() -//TODO: sanitize uuid and executable (size, valid chars etc) + openlog("abrt", LOG_PID, LOG_DAEMON); + logmode = LOGMODE_SYSLOG; + + // Error if daemon is not running + if (!daemon_is_ok()) + error_msg_and_die("daemon is not running, python crash dump aborted"); unsigned setting_MaxCrashReportsSize = 0; parse_conf(NULL, &setting_MaxCrashReportsSize, NULL); @@ -94,14 +125,15 @@ int main(int argc, char** argv) ssize_t len = full_read(STDIN_FILENO, bt, MAX_BT_SIZE-1); if (len < 0) { - perror_msg_and_die("Read error"); + perror_msg_and_die("read error"); } bt[len] = '\0'; if (len == MAX_BT_SIZE-1) { - error_msg("Backtrace size limit exceeded, trimming to " MAX_BT_SIZE_STR); + error_msg("backtrace size limit exceeded, trimming to " MAX_BT_SIZE_STR); } + // This also checks that pid is a valid numeric string char *cmdline = get_cmdline(xatou(pid)); /* never NULL */ // Create directory with the debug dump @@ -109,11 +141,10 @@ int main(int argc, char** argv) snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s", (long)time(NULL), pid); CDebugDump dd; - try { dd.Create(path, getuid()); } catch (CABRTException &e) { - error_msg_and_die("Error while creating debug dump: %s", e.what()); + error_msg_and_die("error while creating crash dump %s: %s", path, e.what()); } dd.SaveText(FILENAME_ANALYZER, "Python"); @@ -128,6 +159,8 @@ int main(int argc, char** argv) dd.SaveText("uid", uid); dd.Close(); + log("saved python crash dump of pid %s to %s", pid, path); + if (setting_MaxCrashReportsSize > 0) { trim_debug_dumps(setting_MaxCrashReportsSize, path); -- cgit From c76edd0dd78d0c85e4ce5dcece432dc53abd8cc6 Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Wed, 13 Jan 2010 10:48:14 +0100 Subject: fix memory leaks in bugzilla --- lib/Plugins/Bugzilla.cpp | 138 ++++++++++++++++++++++++++++++++++++---------- lib/Plugins/Catcut.cpp | 43 ++++++++++----- lib/Utils/abrt_xmlrpc.cpp | 16 +++++- lib/Utils/abrt_xmlrpc.h | 2 +- 4 files changed, 153 insertions(+), 46 deletions(-) diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp index 14eb87f..38a6978 100644 --- a/lib/Plugins/Bugzilla.cpp +++ b/lib/Plugins/Bugzilla.cpp @@ -39,7 +39,8 @@ void ctx::login(const char* login, const char* passwd) xmlrpc_env_init(&env); xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s})", "login", login, "password", passwd); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.login", param, &result); @@ -62,14 +63,16 @@ void ctx::logout() xmlrpc_env_init(&env); xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", ""); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "User.logout", param, &result); xmlrpc_DECREF(param); if (result) xmlrpc_DECREF(result); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); } bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) @@ -77,23 +80,36 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) xmlrpc_env env; xmlrpc_env_init(&env); + // fails only when you write query. when it's done it never fails. xmlrpc_value* param = xmlrpc_build_value(&env, "(s)", to_string(bug_id).c_str()); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.getBug", param, &result); + // we don't need anymore xml structure for calling xmlrpc query(calls only once) xmlrpc_DECREF(param); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* reporter_member = NULL; xmlrpc_struct_find_value(&env, result, "reporter", &reporter_member); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + throw_xml_fault(&env); + } if (reporter_member) { const char* reporter = NULL; xmlrpc_read_string(&env, reporter_member, &reporter); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(reporter_member); + throw_xml_fault(&env); + } bool eq = (strcmp(reporter, login) == 0); free((void*)reporter); @@ -107,7 +123,11 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) xmlrpc_value* cc_member = NULL; xmlrpc_struct_find_value(&env, result, "cc", &cc_member); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + throw_xml_fault(&env); + } if (cc_member) { @@ -117,11 +137,22 @@ bool ctx::check_cc_and_reporter(uint32_t bug_id, const char* login) { xmlrpc_value* item = NULL; xmlrpc_array_read_item(&env, cc_member, i, &item); // Correct - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(cc_member); + throw_xml_fault(&env); + } const char* cc = NULL; xmlrpc_read_string(&env, item, &cc); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(cc_member); + xmlrpc_DECREF(item); + throw_xml_fault(&env); + } bool eq = (strcmp(cc, login) == 0); free((void*)cc); @@ -145,15 +176,19 @@ void ctx::add_plus_one_cc(uint32_t bug_id, const char* login) xmlrpc_env env; xmlrpc_env_init(&env); - xmlrpc_value* param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login); - throw_if_xml_fault_occurred(&env); + // fails only when you write query. when it's done it never fails. + xmlrpc_value* param = xmlrpc_build_value(&env, "({s:i,s:{s:(s)}})", "ids", bug_id, "updates", "add_cc", login); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.update", param, &result); - throw_if_xml_fault_occurred(&env); + // we don't need anymore xml structure for calling xmlrpc query(calls only once) + xmlrpc_DECREF(param); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_DECREF(result); - xmlrpc_DECREF(param); } int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID) @@ -163,36 +198,61 @@ int32_t ctx::check_uuid_in_bugzilla(const char* component, const char* UUID) std::string query = ssprintf("ALL component:\"%s\" statuswhiteboard:\"%s\"", component, UUID); + // fails only when you write query. when it's done it never fails. xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s})", "quicksearch", query.c_str()); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.search", param, &result); - throw_if_xml_fault_occurred(&env); + // we don't need anymore xml structure for calling xmlrpc query(calls only once) xmlrpc_DECREF(param); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* bugs_member = NULL; xmlrpc_struct_find_value(&env, result, "bugs", &bugs_member); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + throw_xml_fault(&env); + } if (bugs_member) { // when array size is equal 0 that means no bug reported uint32_t array_size = xmlrpc_array_size(&env, bugs_member); - throw_if_xml_fault_occurred(&env); - if (array_size == 0) + if (env.fault_occurred) { + xmlrpc_DECREF(result); xmlrpc_DECREF(bugs_member); + throw_xml_fault(&env); + } + else if (array_size == 0) + { xmlrpc_DECREF(result); + xmlrpc_DECREF(bugs_member); return -1; } xmlrpc_value* item = NULL; xmlrpc_array_read_item(&env, bugs_member, 0, &item); // Correct - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(bugs_member); + throw_xml_fault(&env); + } + xmlrpc_value* bug = NULL; xmlrpc_struct_find_value(&env, item, "bug_id", &bug); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(bugs_member); + xmlrpc_DECREF(item); + throw_xml_fault(&env); + } if (bug) { @@ -236,6 +296,7 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport) std::string version; parse_release(release.c_str(), product, version); + // fails only when you write query. when it's done it never fails. xmlrpc_value* param = xmlrpc_build_value(&env, "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})", "product", product.c_str(), "component", component.c_str(), @@ -245,27 +306,39 @@ uint32_t ctx::new_bug(const map_crash_report_t& pCrashReport) "status_whiteboard", status_whiteboard.c_str(), "platform", arch.c_str() ); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Bug.create", param, &result); - throw_if_xml_fault_occurred(&env); + // we don't need anymore xml structure for calling xmlrpc query(calls only once) + xmlrpc_DECREF(param); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* id; xmlrpc_struct_find_value(&env, result, "id", &id); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + throw_xml_fault(&env); + } xmlrpc_int bug_id = -1; if (id) { xmlrpc_read_int(&env, id, &bug_id); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_DECREF(id); + throw_xml_fault(&env); + } log("New bug id: %i", bug_id); update_client(_("New bug id: %i"), bug_id); } xmlrpc_DECREF(result); - xmlrpc_DECREF(param); xmlrpc_DECREF(id); return bug_id; } @@ -287,6 +360,7 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra if (type == CD_ATT) { char *encoded64 = encode_base64(content.c_str(), content.length()); + // fails only when you write query. when it's done it never fails. xmlrpc_value* param = xmlrpc_build_value(&env, "(s{s:s,s:s,s:s,s:s})", bug_id_str, "description", ("File: " + filename).c_str(), @@ -295,12 +369,18 @@ void ctx::add_attachments(const char* bug_id_str, const map_crash_report_t& pCra "data", encoded64 ); free(encoded64); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "bugzilla.addAttachment", param, &result); - xmlrpc_DECREF(result); + // we don't need anymore xml structure for calling xmlrpc query(calls only once) xmlrpc_DECREF(param); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + throw_xml_fault(&env); + } + xmlrpc_DECREF(result); } } } diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp index 52efc57..27b868d 100644 --- a/lib/Plugins/Catcut.cpp +++ b/lib/Plugins/Catcut.cpp @@ -167,11 +167,14 @@ struct_find_int(xmlrpc_env* env, xmlrpc_value* result, { xmlrpc_value* an_xmlrpc_value; xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value); - throw_if_xml_fault_occurred(env); + if (env->fault_occurred) + throw_xml_fault(env); + if (an_xmlrpc_value) { xmlrpc_read_int(env, an_xmlrpc_value, &value); - throw_if_xml_fault_occurred(env); + if (env->fault_occurred) + throw_xml_fault(env); xmlrpc_DECREF(an_xmlrpc_value); return true; } @@ -184,12 +187,14 @@ struct_find_string(xmlrpc_env* env, xmlrpc_value* result, { xmlrpc_value* an_xmlrpc_value; xmlrpc_struct_find_value(env, result, fieldName, &an_xmlrpc_value); - throw_if_xml_fault_occurred(env); + if (env->fault_occurred) + throw_xml_fault(env); if (an_xmlrpc_value) { const char* value_s; xmlrpc_read_string(env, an_xmlrpc_value, &value_s); - throw_if_xml_fault_occurred(env); + if (env->fault_occurred) + throw_xml_fault(env); value = value_s; xmlrpc_DECREF(an_xmlrpc_value); free((void*)value_s); @@ -228,20 +233,24 @@ ctx::login(const char* login, const char* passwd) xmlrpc_env_init(&env); xmlrpc_value* param = xmlrpc_build_value(&env, "(ss)", login, passwd); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.auth", param, &result); xmlrpc_DECREF(param); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value *cookie_xml; const char *cookie; string cookie_str; xmlrpc_struct_find_value(&env, result, "cookie", &cookie_xml); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_read_string(&env, cookie_xml, &cookie); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); cookie_str = cookie; /* xmlrpc_read_string returns *malloc'ed ptr*. * doc is not very clear on it, but I looked in xmlrpc sources. */ @@ -284,20 +293,24 @@ ctx::new_bug(const char *auth_cookie, const map_crash_report_t& pCrashReport) "status_whiteboard", status_whiteboard.c_str(), "platform", arch.c_str() ); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value *result; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.createTicket", param, &result); xmlrpc_DECREF(param); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value *bug_id_xml; const char *bug_id; string bug_id_str; xmlrpc_struct_find_value(&env, result, "ticket", &bug_id_xml); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_read_string(&env, bug_id_xml, &bug_id); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); bug_id_str = bug_id; log("New bug id: %s", bug_id); update_client(_("New bug id: %s"), bug_id); @@ -321,12 +334,14 @@ ctx::request_upload(const char* auth_cookie, const char* pTicketName, pTicketName, fileName, description); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); xmlrpc_value* result = NULL; xmlrpc_client_call2(&env, m_pClient, m_pServer_info, "Catcut.requestUpload", param, &result); xmlrpc_DECREF(param); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); string URL; bool has_URL = struct_find_string(&env, result, "uri", URL); diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp index ae1d098..e3a4648 100644 --- a/lib/Utils/abrt_xmlrpc.cpp +++ b/lib/Utils/abrt_xmlrpc.cpp @@ -15,6 +15,16 @@ CURL* xcurl_easy_init() return curl; } +#if 1 +void throw_xml_fault(xmlrpc_env *env) +{ + std::string errmsg = ssprintf("XML-RPC Fault: %s(%d)", env->fault_string, env->fault_code); + xmlrpc_env_clean(env); // this is needed ONLY if fault_occurred + xmlrpc_env_init(env); // just in case user catches ex and _continues_ to use env + error_msg("%s", errmsg.c_str()); // show error in daemon log + throw CABRTException(EXCEP_PLUGIN, errmsg.c_str()); +} +#else void throw_if_xml_fault_occurred(xmlrpc_env *env) { if (env->fault_occurred) @@ -26,6 +36,7 @@ void throw_if_xml_fault_occurred(xmlrpc_env *env) throw CABRTException(EXCEP_PLUGIN, errmsg.c_str()); } } +#endif void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify) { @@ -60,15 +71,16 @@ void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool no_ssl_verify) PACKAGE_NAME, VERSION, &clientParms, XMLRPC_CPSIZE(transportparm_size), &m_pClient); - throw_if_xml_fault_occurred(&env); + if (env.fault_occurred) + throw_xml_fault(&env); m_pServer_info = xmlrpc_server_info_new(&env, url); if (env.fault_occurred) { xmlrpc_client_destroy(m_pClient); m_pClient = NULL; + throw_xml_fault(&env); } - throw_if_xml_fault_occurred(&env); } void abrt_xmlrpc_conn::destroy_xmlrpc_client() diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h index 352e80c..a8bd2cc 100644 --- a/lib/Utils/abrt_xmlrpc.h +++ b/lib/Utils/abrt_xmlrpc.h @@ -24,7 +24,7 @@ struct abrt_xmlrpc_conn { }; /* Utility functions */ -void throw_if_xml_fault_occurred(xmlrpc_env *env); +void throw_xml_fault(xmlrpc_env *env); CURL* xcurl_easy_init(); #endif -- cgit From 82c1b530de565ec0dab054289c398fc1f5e73507 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 12:06:32 +0100 Subject: don't use deleted variable --- src/Daemon/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index a6550e7..1c7237d 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -235,9 +235,9 @@ void CPluginManager::UnLoadPlugin(const char *pName) delete it_plugin->second; m_mapPlugins.erase(it_plugin); } - delete it_module->second; m_mapLoadedModules.erase(it_module); log("UnRegistered %s plugin %s", plugin_type_str[it_module->second->GetType()], pName); + delete it_module->second; } } -- cgit From f5925030be2963ddf257e6768dcd5712b0e6df08 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 12:44:04 +0100 Subject: fixed the switched lines 2nd try --- src/Daemon/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 1c7237d..e14f852 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -235,8 +235,8 @@ void CPluginManager::UnLoadPlugin(const char *pName) delete it_plugin->second; m_mapPlugins.erase(it_plugin); } - m_mapLoadedModules.erase(it_module); log("UnRegistered %s plugin %s", plugin_type_str[it_module->second->GetType()], pName); + m_mapLoadedModules.erase(it_module); delete it_module->second; } } -- cgit From df1d7cd05d8f6abba8c713e773828deee19baf22 Mon Sep 17 00:00:00 2001 From: Karel Klic Date: Wed, 13 Jan 2010 14:21:20 +0100 Subject: Better error messages for abrt-backtrace execution --- lib/Plugins/CCpp.cpp | 22 +++++++++++++++++++--- src/Backtrace/main.c | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 6c200d0..e0db9cf 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -621,13 +621,29 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) { perror_msg("abrt-backtrace not executed properly, " "status: %x signal: %d", status, WIFSIGNALED(status)); - } else + } + else { int exit_status = WEXITSTATUS(status); - if (exit_status != 0) + if (exit_status == 79) /* EX_PARSINGFAILED */ + { + /* abrt-backtrace returns alternative backtrace + representation in this case, so everything will work + as expected except worse duplication detection */ + log_msg("abrt-backtrace failed to parse the backtrace"); + } + else if (exit_status == 80) /* EX_THREADDETECTIONFAILED */ + { + /* abrt-backtrace returns backtrace with all threads + in this case, so everything will work as expected + except worse duplication detection */ + log_msg("abrt-backtrace failed to determine crash frame"); + } + else if (exit_status != 0) { + /* this is unexpected problem and it should be investigated */ error_msg("abrt-backtrace run failed, exit value: %d", - exit_status); + exit_status); } } diff --git a/src/Backtrace/main.c b/src/Backtrace/main.c index 7dfba43..5e69338 100644 --- a/src/Backtrace/main.c +++ b/src/Backtrace/main.c @@ -28,8 +28,8 @@ /* Too large files are trimmed. */ #define FILE_SIZE_LIMIT 20000000 /* ~ 20 MB */ -#define EX_PARSINGFAILED EX__MAX + 1 -#define EX_THREADDETECTIONFAILED EX__MAX + 2 +#define EX_PARSINGFAILED EX__MAX + 1 /* = 79 */ +#define EX_THREADDETECTIONFAILED EX__MAX + 2 /* = 80 */ const char *argp_program_version = "abrt-backtrace " VERSION; const char *argp_program_bug_address = ""; -- cgit From 38aed8f42c135b9a7b4b2785b877935d3746352b Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 14:52:46 +0100 Subject: re-enable GetPluginSettings in TicketUploader - we need this method to get defaults stored in TicketUploader.conf, this methods can be removed once we implement the tool to edit the config files --- lib/Plugins/TicketUploader.cpp | 25 ++++++++++++------------- lib/Plugins/TicketUploader.h | 5 ++--- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp index 3fb7bcd..608ee40 100644 --- a/lib/Plugins/TicketUploader.cpp +++ b/lib/Plugins/TicketUploader.cpp @@ -396,19 +396,18 @@ void CTicketUploader::SetSettings(const map_plugin_settings_t& pSettings) } } -//ok to delete? -//const map_plugin_settings_t& CTicketUploader::GetSettings() -//{ -// m_pSettings["Customer"] = m_sCustomer; -// m_pSettings["Ticket"] = m_sTicket; -// m_pSettings["URL"] = m_sURL; -// m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no"; -// m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no"; -// m_pSettings["RetryCount"] = to_string(m_nRetryCount); -// m_pSettings["RetryDelay"] = to_string(m_nRetryDelay); -// -// return m_pSettings; -//} +const map_plugin_settings_t& CTicketUploader::GetSettings() +{ + m_pSettings["Customer"] = m_sCustomer; + m_pSettings["Ticket"] = m_sTicket; + m_pSettings["URL"] = m_sURL; + m_pSettings["Encrypt"] = m_bEncrypt ? "yes" : "no"; + m_pSettings["Upload"] = m_bEncrypt ? "yes" : "no"; + m_pSettings["RetryCount"] = to_string(m_nRetryCount); + m_pSettings["RetryDelay"] = to_string(m_nRetryDelay); + + return m_pSettings; +} PLUGIN_INFO(REPORTER, CTicketUploader, diff --git a/lib/Plugins/TicketUploader.h b/lib/Plugins/TicketUploader.h index e00596f..1bc8f6b 100644 --- a/lib/Plugins/TicketUploader.h +++ b/lib/Plugins/TicketUploader.h @@ -27,7 +27,7 @@ #include "Plugin.h" #include "Reporter.h" -#include "CrashTypes.h" +//#include "CrashTypes.h" class CTicketUploader : public CReporter { @@ -45,8 +45,7 @@ class CTicketUploader : public CReporter public: CTicketUploader(); virtual ~CTicketUploader(); -//ok to delete? -// virtual const map_plugin_settings_t& GetSettings(); + virtual const map_plugin_settings_t& GetSettings(); virtual void SetSettings(const map_plugin_settings_t& pSettings); virtual std::string Report(const map_crash_report_t& pCrashReport, -- cgit From 4d57287e4f6d9ba62e65a59de3ed0fdd749fb7e6 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 14:53:15 +0100 Subject: remeove timeout when authorization is done --- lib/Utils/Polkit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Utils/Polkit.cpp b/lib/Utils/Polkit.cpp index 8bd0eb6..a7e4a5d 100644 --- a/lib/Utils/Polkit.cpp +++ b/lib/Utils/Polkit.cpp @@ -48,7 +48,7 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id) authority = polkit_authority_get(); cancellable = g_cancellable_new(); - g_timeout_add(POLKIT_TIMEOUT * 1000, + guint cancel_timeout = g_timeout_add(POLKIT_TIMEOUT * 1000, (GSourceFunc) do_cancel, cancellable); @@ -60,7 +60,7 @@ static PolkitResult do_check(PolkitSubject *subject, const char *action_id) cancellable, &error); g_object_unref(authority); - + g_source_remove(cancel_timeout); if (error) { g_error_free(error); -- cgit From d188c8f886ecca7f9e0ff02dfadee50cd917c74b Mon Sep 17 00:00:00 2001 From: Nikola Pajkovsky Date: Wed, 13 Jan 2010 15:16:17 +0100 Subject: fix memory leaks in catcut plugin --- lib/Plugins/Bugzilla.cpp | 3 +++ lib/Plugins/Catcut.conf | 1 + 2 files changed, 4 insertions(+) diff --git a/lib/Plugins/Bugzilla.cpp b/lib/Plugins/Bugzilla.cpp index 38a6978..6f0f8d7 100644 --- a/lib/Plugins/Bugzilla.cpp +++ b/lib/Plugins/Bugzilla.cpp @@ -13,6 +13,9 @@ #define XML_RPC_SUFFIX "/xmlrpc.cgi" +/* + * TODO: npajkovs: better deallocation of xmlrpc value + */ /* * Static namespace for xmlrpc stuff. diff --git a/lib/Plugins/Catcut.conf b/lib/Plugins/Catcut.conf index 456d7f8..913b6d1 100644 --- a/lib/Plugins/Catcut.conf +++ b/lib/Plugins/Catcut.conf @@ -1,3 +1,4 @@ +Enabled=1 # Catcut URL CatcutURL = http://127.0.0.1:8080/catcut/xmlrpc # yes means that ssl certificates will not be checked -- cgit From 9e3970c52f800739b4f554a2ec4ef236b566fb00 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Jan 2010 16:47:39 +0100 Subject: *: disable plugin loading/unloading through GUI. Document keyring a bit Signed-off-by: Denys Vlasenko --- src/Daemon/CommLayerServerDBus.cpp | 4 +++ src/Daemon/MiddleWare.cpp | 4 ++- src/Daemon/PluginManager.cpp | 3 +- src/Daemon/PluginManager.h | 2 ++ src/Gui/ABRTPlugin.py | 39 +++++++++++----------- src/Gui/CCDBusBackend.py | 16 +++++---- src/Gui/CCReporterDialog.py | 2 +- src/Gui/ConfBackend.py | 22 ++++++++++-- src/Gui/PluginList.py | 4 +-- src/Gui/PluginsSettingsDialog.py | 68 ++++++++++++++++++++------------------ 10 files changed, 98 insertions(+), 66 deletions(-) diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index 9222c59..8589941 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -393,6 +393,7 @@ static int handle_SetPluginSettings(DBusMessage* call, DBusMessage* reply) return 0; } +#ifdef PLUGIN_DYNAMIC_LOAD_UNLOAD static int handle_RegisterPlugin(DBusMessage* call, DBusMessage* reply) { int r; @@ -432,6 +433,7 @@ static int handle_UnRegisterPlugin(DBusMessage* call, DBusMessage* reply) send_flush_and_unref(reply); return 0; } +#endif static int handle_GetSettings(DBusMessage* call, DBusMessage* reply) { @@ -496,10 +498,12 @@ static DBusHandlerResult message_received(DBusConnection* conn, DBusMessage* msg r = handle_GetPluginSettings(msg, reply); else if (strcmp(member, "SetPluginSettings") == 0) r = handle_SetPluginSettings(msg, reply); +#ifdef PLUGIN_DYNAMIC_LOAD_UNLOAD else if (strcmp(member, "RegisterPlugin") == 0) r = handle_RegisterPlugin(msg, reply); else if (strcmp(member, "UnRegisterPlugin") == 0) r = handle_UnRegisterPlugin(msg, reply); +#endif else if (strcmp(member, "GetSettings") == 0) r = handle_GetSettings(msg, reply); else if (strcmp(member, "SetSettings") == 0) diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index a348a92..70527eb 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -517,7 +517,9 @@ report_status_t Report(const map_crash_report_t& pCrashReport, #endif ret[plugin_name].push_back("1"); // REPORT_STATUS_IDX_FLAG ret[plugin_name].push_back(res); // REPORT_STATUS_IDX_MSG - message += res + "\n"; + if (message != "") + message += "; "; + message += res; } } catch (CABRTException& e) diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index e14f852..136277c 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -241,6 +241,7 @@ void CPluginManager::UnLoadPlugin(const char *pName) } } +#ifdef PLUGIN_DYNAMIC_LOAD_UNLOAD void CPluginManager::RegisterPluginDBUS(const char *pName, const char *pDBUSSender) { int polkit_result = polkit_check_authorization(pDBUSSender, @@ -267,7 +268,7 @@ void CPluginManager::UnRegisterPluginDBUS(const char *pName, const char *pDBUSSe log("user %s not authorized, returned %d", pDBUSSender, polkit_result); } } - +#endif CAnalyzer* CPluginManager::GetAnalyzer(const char *pName) { diff --git a/src/Daemon/PluginManager.h b/src/Daemon/PluginManager.h index 65058a5..d3e686c 100644 --- a/src/Daemon/PluginManager.h +++ b/src/Daemon/PluginManager.h @@ -80,6 +80,7 @@ class CPluginManager * @param pName A plugin name. */ void UnLoadPlugin(const char *pName); +#ifdef PLUGIN_DYNAMIC_LOAD_UNLOAD /** * A method, which registers particular plugin. * @param pName A plugin name. @@ -92,6 +93,7 @@ class CPluginManager * @param pDBUSSender DBUS user identification */ void UnRegisterPluginDBUS(const char *pName, const char *pDBUSSender); +#endif /** * A method, which returns instance of particular analyzer plugin. * @param pName A plugin name. diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py index ea90b87..03b61fb 100644 --- a/src/Gui/ABRTPlugin.py +++ b/src/Gui/ABRTPlugin.py @@ -16,39 +16,40 @@ from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError class PluginSettings(dict): def __init__(self): dict.__init__(self) - self.conf = None + self.client_side_conf = None try: - self.conf = ConfBackendGnomeKeyring() + self.client_side_conf = ConfBackendGnomeKeyring() except ConfBackendInitError, e: print e pass def check(self): + # if present, these should be non-empty for key in ["Password", "Login"]: if key in self.keys(): - # some of the required keys is missing if not self[key]: + # some of the required keys are missing return False # settings are OK return True - def load(self, name, default_settings): + def load_daemon_settings(self, name, daemon_settings): # load settings from daemon - for key in default_settings.keys(): - self[str(key)] = str(default_settings[key]) + for key in daemon_settings.keys(): + self[str(key)] = str(daemon_settings[key]) - if self.conf: - settings = self.conf.load(name) - # overwrite defaluts with user setting + if self.client_side_conf: + settings = self.client_side_conf.load(name) + # overwrite daemon data with user setting for key in settings.keys(): - # only rewrite keys needed by the plugin - # e.g we don't want a pass field for logger - if key in default_settings.keys(): + # only rewrite keys which exist in plugin's keys. + # e.g. we don't want a password field for logger plugin + if key in daemon_settings.keys(): self[str(key)] = str(settings[key]) - def save(self, name): - if self.conf: - self.conf.save(name, self) + def save_on_client_side(self, name): + if self.client_side_conf: + self.client_side_conf.save(name, self) class PluginInfo(): """Class to represent common plugin info""" @@ -90,11 +91,11 @@ class PluginInfo(): def __getitem__(self, item): return self.__dict__[item] - def load_settings(self, default_settings): + def load_daemon_settings(self, daemon_settings): if self.Name: - self.Settings.load(self.Name, default_settings) + self.Settings.load_daemon_settings(self.Name, daemon_settings) else: print _("Plugin name is not set, can't load its settings") - def save_settings(self): - self.Settings.save(str(self.Name)) + def save_settings_on_client_side(self): + self.Settings.save_on_client_side(str(self.Name)) diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py index 85987e8..ac378f4 100644 --- a/src/Gui/CCDBusBackend.py +++ b/src/Gui/CCDBusBackend.py @@ -167,7 +167,10 @@ class DBusManager(gobject.GObject): def Report(self, report, reporters_settings = None): # map < Plguin_name vec > - self.daemon().Report(report, reporters_settings, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60) + if reporters_settings: + self.daemon().Report(report, reporters_settings, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60) + else: + self.daemon().Report(report, reply_handler=self.report_done, error_handler=self.error_handler_cb, timeout=60) def DeleteDebugDump(self,UUID): return self.daemon().DeleteDebugDump(UUID) @@ -192,11 +195,12 @@ class DBusManager(gobject.GObject): # print i return settings - def registerPlugin(self, plugin_name): - return self.daemon().RegisterPlugin(plugin_name) - - def unRegisterPlugin(self, plugin_name): - return self.daemon().UnRegisterPlugin(plugin_name) +# "Enable" toggling in GUI is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD +# def registerPlugin(self, plugin_name): +# return self.daemon().RegisterPlugin(plugin_name) +# +# def unRegisterPlugin(self, plugin_name): +# return self.daemon().UnRegisterPlugin(plugin_name) def setPluginSettings(self, plugin_name, plugin_settings): return self.daemon().SetPluginSettings(plugin_name, plugin_settings) diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py index 09a9c91..bba8942 100644 --- a/src/Gui/CCReporterDialog.py +++ b/src/Gui/CCReporterDialog.py @@ -131,7 +131,7 @@ class ReporterDialog(): ui.dehydrate() if plugin.Settings.check(): try: - plugin.save_settings() + plugin.save_settings_on_client_side() except Exception, e: gui_error_message(_("Can't save plugin settings:\n %s" % e)) box = image.get_parent() diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py index 5e26f3e..024a103 100644 --- a/src/Gui/ConfBackend.py +++ b/src/Gui/ConfBackend.py @@ -38,6 +38,22 @@ class ConfBackend(object): raise NotImplementedError +# We use Gnome keyring in the following way: +# we store passwords for each plugin in a key named "abrt:". +# The value of the key becomes the value of "Password" setting. +# Other settings (if plugin has them) are stored as attributes of this key. +# +# Example: Key "abrt:Bugzilla" with bugzilla password as value, and with attributes: +# +# AbrtPluginInfo: Bugzilla +# NoSSLVerify: yes +# Login: user@host.com +# BugzillaURL: https://host.with.bz.com/ +# +# The attribute "AbrtPluginInfo" is special, it is used for retrieving +# the key via keyring API find_items_sync() function. + + class ConfBackendGnomeKeyring(ConfBackend): def __init__(self): ConfBackend.__init__(self) @@ -47,7 +63,7 @@ class ConfBackendGnomeKeyring(ConfBackend): self.default_key_ring = gkey.get_default_keyring_sync() except: # could happen if keyring daemon is running, but we run gui under - # user who is not owner is the running session - using su + # user who is not the owner of the running session - using su raise ConfBackendInitError(_("Can't get default keyring")) def save(self, name, settings): @@ -62,7 +78,7 @@ class ConfBackendGnomeKeyring(ConfBackend): # nothing found pass except gkey.DeniedError: - raise ConfBackendSaveError(_("Acces to gnome-keyring has been denied, plugins settings won't be saved.")) + raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved.")) # delete all items containg "AbrtPluginInfo":, so we always have only 1 item per plugin for item in item_list: @@ -79,7 +95,7 @@ class ConfBackendGnomeKeyring(ConfBackend): password, True) except gkey.DeniedError, e: - raise ConfBackendSaveError(_("Acces to gnome-keyring has been denied, plugins settings won't be saved.")) + raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved.")) def load(self, name): item_list = None diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py index e57040d..79df126 100644 --- a/src/Gui/PluginList.py +++ b/src/Gui/PluginList.py @@ -20,8 +20,8 @@ class PluginInfoList(list): entry.__dict__[column] = row[column] if entry.Enabled == "yes": #entry.Settings = PluginSettings(self.dm.getPluginSettings(str(entry))) - default_settings = self.dm.getPluginSettings(str(entry)) - entry.load_settings(default_settings) + daemon_settings = self.dm.getPluginSettings(str(entry)) + entry.load_daemon_settings(daemon_settings) self.append(entry) self.ddict[entry.getName()] = entry else: diff --git a/src/Gui/PluginsSettingsDialog.py b/src/Gui/PluginsSettingsDialog.py index 8453385..5feda4a 100644 --- a/src/Gui/PluginsSettingsDialog.py +++ b/src/Gui/PluginsSettingsDialog.py @@ -44,20 +44,21 @@ class PluginsSettingsDialog: column.set_attributes(column.gray_background, visible=3, cell_background=4) column.set_resizable(True) - # toggle - group_name_renderer = gtk.CellRendererText() - toggle_renderer = gtk.CellRendererToggle() - toggle_renderer.set_property('activatable', True) - toggle_renderer.connect( 'toggled', self.on_enabled_toggled, self.pluginsListStore ) - column = gtk.TreeViewColumn(_('Enabled')) - column.pack_start(toggle_renderer, True) - column.pack_start(group_name_renderer, True) - column.add_attribute( toggle_renderer, "active", 1) - column.add_attribute( toggle_renderer, "visible", 2) - column.add_attribute( group_name_renderer, "visible", 3) - column.add_attribute( group_name_renderer, "markup", 0) - column.add_attribute( group_name_renderer, "cell_background", 4) - self.pluginlist.insert_column(column, 0) +# "Enable" toggle column is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD +# # toggle +# group_name_renderer = gtk.CellRendererText() +# toggle_renderer = gtk.CellRendererToggle() +# toggle_renderer.set_property('activatable', True) +# toggle_renderer.connect( 'toggled', self.on_enabled_toggled, self.pluginsListStore ) +# column = gtk.TreeViewColumn(_('Enabled')) +# column.pack_start(toggle_renderer, True) +# column.pack_start(group_name_renderer, True) +# column.add_attribute( toggle_renderer, "active", 1) +# column.add_attribute( toggle_renderer, "visible", 2) +# column.add_attribute( group_name_renderer, "visible", 3) +# column.add_attribute( group_name_renderer, "markup", 0) +# column.add_attribute( group_name_renderer, "cell_background", 4) +# self.pluginlist.insert_column(column, 0) #connect signals self.pluginlist.connect("cursor-changed", self.on_tvDumps_cursor_changed) @@ -65,24 +66,25 @@ class PluginsSettingsDialog: self.builder.get_object("bClose").connect("clicked", self.on_bClose_clicked) self.builder.get_object("bConfigurePlugin").set_sensitive(False) - def on_enabled_toggled(self,cell, path, model): - plugin = model[path][model.get_n_columns()-1] - if plugin: - if model[path][1]: - #print "self.ccdaemon.UnRegisterPlugin(%s)" % (plugin.getName()) - self.ccdaemon.unRegisterPlugin(plugin.getName()) - # FIXME: create class plugin and move this into method Plugin.Enable() - plugin.Enabled = "no" - plugin.Settings = None - else: - #print "self.ccdaemon.RegisterPlugin(%s)" % (model[path][model.get_n_columns()-1]) - self.ccdaemon.registerPlugin(plugin.getName()) - # FIXME: create class plugin and move this into method Plugin.Enable() - plugin.Enabled = "yes" - default_settings = self.ccdaemon.getPluginSettings(plugin.getName()) - plugin.Settings = PluginSettings() - plugin.Settings.load(plugin.getName(), default_settings) - model[path][1] = not model[path][1] +# "Enable" toggle column is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD +# def on_enabled_toggled(self,cell, path, model): +# plugin = model[path][model.get_n_columns()-1] +# if plugin: +# if model[path][1]: +# #print "self.ccdaemon.UnRegisterPlugin(%s)" % (plugin.getName()) +# self.ccdaemon.unRegisterPlugin(plugin.getName()) +# # FIXME: create class plugin and move this into method Plugin.Enable() +# plugin.Enabled = "no" +# plugin.Settings = None +# else: +# #print "self.ccdaemon.RegisterPlugin(%s)" % (model[path][model.get_n_columns()-1]) +# self.ccdaemon.registerPlugin(plugin.getName()) +# # FIXME: create class plugin and move this into method Plugin.Enable() +# plugin.Enabled = "yes" +# default_settings = self.ccdaemon.getPluginSettings(plugin.getName()) +# plugin.Settings = PluginSettings() +# plugin.Settings.load(plugin.getName(), default_settings) +# model[path][1] = not model[path][1] def filter_plugins(self, model, miter, data): return True @@ -135,7 +137,7 @@ class PluginsSettingsDialog: ui.dehydrate() if pluginfo.Settings: try: - pluginfo.save_settings() + pluginfo.save_settings_on_client_side() # FIXME: do we need to call this? all reporters set their settings # when Report() is called self.ccdaemon.setPluginSettings(pluginfo.getName(), pluginfo.Settings) -- cgit From 7f1a96006b50365f54ff94d110ee4011c1b9a32a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Jan 2010 18:02:22 +0100 Subject: fix plugin type display in GUI Signed-off-by: Denys Vlasenko --- src/Gui/CCMainWindow.py | 6 ++-- src/Gui/PluginsSettingsDialog.py | 69 ++++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py index 77ce3d3..f4e3a73 100644 --- a/src/Gui/CCMainWindow.py +++ b/src/Gui/CCMainWindow.py @@ -69,9 +69,9 @@ class MainWindow(): #icon, package_name, application, date, crash_rate, user, is_reported, ?object? self.dumpsListStore = gtk.ListStore(gtk.gdk.Pixbuf, str,str,str,str,str,bool, object) # set filter - self.modelfilter = self.dumpsListStore.filter_new() - self.modelfilter.set_visible_func(self.filter_dumps, None) - self.dlist.set_model(self.modelfilter) + modelfilter = self.dumpsListStore.filter_new() + modelfilter.set_visible_func(self.filter_dumps, None) + self.dlist.set_model(modelfilter) # add pixbuff separatelly icon_column = gtk.TreeViewColumn(_("Icon")) icon_column.cell = gtk.CellRendererPixbuf() diff --git a/src/Gui/PluginsSettingsDialog.py b/src/Gui/PluginsSettingsDialog.py index 5feda4a..0d41962 100644 --- a/src/Gui/PluginsSettingsDialog.py +++ b/src/Gui/PluginsSettingsDialog.py @@ -6,10 +6,12 @@ from PluginSettingsUI import PluginSettingsUI from ABRTPlugin import PluginSettings, PluginInfo from abrt_utils import _ + class PluginsSettingsDialog: def __init__(self, parent, daemon): #print "Settings dialog init" self.ccdaemon = daemon + self.builder = gtk.Builder() builderfile = "%s%ssettings.glade" % (sys.path[0],"/") #print builderfile @@ -22,43 +24,41 @@ class PluginsSettingsDialog: raise Exception(_("Can't load gui description for SettingsDialog!")) #self.window.set_parent(parent) - self.pluginlist = self.builder.get_object("tvSettings") + self.pluginlist = self.builder.get_object("tvSettings") # a TreeView # cell_text, toggle_active, toggle_visible, group_name_visible, color, plugin self.pluginsListStore = gtk.TreeStore(str, bool, bool, bool, str, object) # set filter - self.modelfilter = self.pluginsListStore.filter_new() - self.modelfilter.set_visible_func(self.filter_plugins, None) - self.pluginlist.set_model(self.modelfilter) - # =============================================== - columns = [None]*1 - columns[0] = gtk.TreeViewColumn(_("Name")) + modelfilter = self.pluginsListStore.filter_new() + modelfilter.set_visible_func(self.filter_plugins, None) + self.pluginlist.set_model(modelfilter) - # create list - for column in columns: - n = self.pluginlist.append_column(column) - column.cell = gtk.CellRendererText() - column.gray_background = gtk.CellRendererText() - column.pack_start(column.cell, True) - column.pack_start(column.gray_background, True) - column.set_attributes(column.cell, markup=(n-1), visible=2) - column.set_attributes(column.gray_background, visible=3, cell_background=4) - column.set_resizable(True) + # Create/configure columns and add them to pluginlist + # column "name" has two kind of cells: + column = gtk.TreeViewColumn(_("Name")) + # cells for individual plugins (white) + cell_name = gtk.CellRendererText() + column.pack_start(cell_name, True) + column.set_attributes(cell_name, markup=0, visible=2) # show 0th field (plugin name) from data items if 2th field is true + # cells for plugin types (gray) + cell_plugin_type = gtk.CellRendererText() + column.pack_start(cell_plugin_type, True) + column.add_attribute(cell_plugin_type, "visible", 3) + column.add_attribute(cell_plugin_type, "markup", 0) + column.add_attribute(cell_plugin_type, "cell_background", 4) + # column "name" is ready, insert + column.set_resizable(True) + self.pluginlist.append_column(column) # "Enable" toggle column is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD -# # toggle -# group_name_renderer = gtk.CellRendererText() -# toggle_renderer = gtk.CellRendererToggle() -# toggle_renderer.set_property('activatable', True) -# toggle_renderer.connect( 'toggled', self.on_enabled_toggled, self.pluginsListStore ) -# column = gtk.TreeViewColumn(_('Enabled')) -# column.pack_start(toggle_renderer, True) -# column.pack_start(group_name_renderer, True) -# column.add_attribute( toggle_renderer, "active", 1) -# column.add_attribute( toggle_renderer, "visible", 2) -# column.add_attribute( group_name_renderer, "visible", 3) -# column.add_attribute( group_name_renderer, "markup", 0) -# column.add_attribute( group_name_renderer, "cell_background", 4) -# self.pluginlist.insert_column(column, 0) +# column = gtk.TreeViewColumn(_("Enabled")) +# # column "enabled" has one kind of cells: +# cell_toggle_enable = gtk.CellRendererToggle() +# cell_toggle_enable.set_property("activatable", True) +# cell_toggle_enable.connect("toggled", self.on_enabled_toggled, self.pluginsListStore) +# column.pack_start(cell_toggle_enable, True) +# column.add_attribute(cell_toggle_enable, "active", 1) +# column.add_attribute(cell_toggle_enable, "visible", 2) +# self.pluginlist.append_column(column) #connect signals self.pluginlist.connect("cursor-changed", self.on_tvDumps_cursor_changed) @@ -88,6 +88,7 @@ class PluginsSettingsDialog: def filter_plugins(self, model, miter, data): return True + def hydrate(self): #print "settings hydrate" self.pluginsListStore.clear() @@ -100,13 +101,13 @@ class PluginsSettingsDialog: #gui_error_message("Error while loading plugins info, please check if abrt daemon is running\n %s" % e) plugin_rows = {} for plugin_type in PluginInfo.types.keys(): - it = self.pluginsListStore.append(None, ["%s" % (PluginInfo.types[plugin_type]),0 , 0, 1,"gray", None]) + it = self.pluginsListStore.append(None, ["%s" % PluginInfo.types[plugin_type], 0, 0, 1, "gray", None]) plugin_rows[plugin_type] = it for entry in pluginlist: - n = self.pluginsListStore.append(plugin_rows[entry.getType()],["%s\n%s" % (entry.getName(), entry.Description), entry.Enabled == "yes", 1, 0, "white", entry]) + self.pluginsListStore.append(plugin_rows[entry.getType()], + ["%s\n%s" % (entry.getName(), entry.Description), entry.Enabled == "yes", 1, 0, "white", entry]) self.pluginlist.expand_all() - def dehydrate(self): # we have nothing to save, plugin's does the work pass -- cgit From a3b88d29cc65b586dff718d48ba732074c261795 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 18:03:48 +0100 Subject: Added "Enabled = yes" to all plugin's config files --- lib/Plugins/Catcut.conf | 1 + lib/Plugins/FileTransfer.conf | 1 + lib/Plugins/Kerneloops.conf | 1 + lib/Plugins/Logger.conf | 3 ++- lib/Plugins/Mailx.conf | 1 + lib/Plugins/Python.conf | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 lib/Plugins/Python.conf diff --git a/lib/Plugins/Catcut.conf b/lib/Plugins/Catcut.conf index 913b6d1..a0249fd 100644 --- a/lib/Plugins/Catcut.conf +++ b/lib/Plugins/Catcut.conf @@ -7,3 +7,4 @@ NoSSLVerify = no Login = gavin # your password Password = junk +Enabled = yes \ No newline at end of file diff --git a/lib/Plugins/FileTransfer.conf b/lib/Plugins/FileTransfer.conf index 75e5671..c92eaee 100644 --- a/lib/Plugins/FileTransfer.conf +++ b/lib/Plugins/FileTransfer.conf @@ -17,3 +17,4 @@ RetryCount = 3 #how long we wait between we retry the upload (in seconds) RetryDelay = 20 +Enabled = yes \ No newline at end of file diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/Kerneloops.conf index 5623596..1db2436 100644 --- a/lib/Plugins/Kerneloops.conf +++ b/lib/Plugins/Kerneloops.conf @@ -15,3 +15,4 @@ SysLogFile = /var/log/messages # KerneloopsReporter configuration ################################## SubmitURL = http://submit.kerneloops.org/submitoops.php +Enabled = yes \ No newline at end of file diff --git a/lib/Plugins/Logger.conf b/lib/Plugins/Logger.conf index 901b3cf..39ba47e 100644 --- a/lib/Plugins/Logger.conf +++ b/lib/Plugins/Logger.conf @@ -2,4 +2,5 @@ LogPath = /var/log/abrt-logger -AppendLogs = yes \ No newline at end of file +AppendLogs = yes +Enabled = yes \ No newline at end of file diff --git a/lib/Plugins/Mailx.conf b/lib/Plugins/Mailx.conf index 44c1d18..de19709 100644 --- a/lib/Plugins/Mailx.conf +++ b/lib/Plugins/Mailx.conf @@ -13,3 +13,4 @@ EmailTo = root@localhost # Warning! enabling this may cause sending a lot of MB via email SendBinaryData = no +Enabled = yes \ No newline at end of file diff --git a/lib/Plugins/Python.conf b/lib/Plugins/Python.conf new file mode 100644 index 0000000..75d2229 --- /dev/null +++ b/lib/Plugins/Python.conf @@ -0,0 +1 @@ +Enabled = yes \ No newline at end of file -- cgit From e3022d5444371b6f2a8537fe0f9c4898188659ae Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 18:22:23 +0100 Subject: added Python.conf --- lib/Plugins/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Plugins/Makefile.am b/lib/Plugins/Makefile.am index f93f510..df35416 100644 --- a/lib/Plugins/Makefile.am +++ b/lib/Plugins/Makefile.am @@ -32,7 +32,8 @@ dist_pluginsconf_DATA = \ Bugzilla.conf \ Catcut.conf \ TicketUploader.conf \ - FileTransfer.conf + FileTransfer.conf \ + Python.conf man_MANS = abrt-FileTransfer.7 abrt-Bugzilla.7 abrt-KerneloopsReporter.7 \ abrt-KerneloopsScanner.7 abrt-Logger.7 abrt-Mailx.7 abrt-plugins.7 \ -- cgit From 6a5213d686669b5b4e425bb7d97a96db57345b30 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Wed, 13 Jan 2010 18:23:17 +0100 Subject: added Python.conf to spec file --- abrt.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/abrt.spec b/abrt.spec index c64e67a..e82a7f0 100644 --- a/abrt.spec +++ b/abrt.spec @@ -386,10 +386,12 @@ fi %files addon-python %defattr(-,root,root,-) +%config(noreplace) %{_sysconfdir}/%{name}/plugins/Python.conf %attr(4755, abrt, abrt) %{_libexecdir}/abrt-hook-python %{_libdir}/%{name}/libPython.so* %{python_site}/*.py* + %files cli %defattr(-,root,root,-) %{_bindir}/abrt-cli -- cgit From b3938fc6d23373e8331385e52ca36d3eb0ef7337 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Jan 2010 18:34:33 +0100 Subject: add an URL to Gnome keyring API (it wasn't trivial to google for) Signed-off-by: Denys Vlasenko --- src/Gui/ConfBackend.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py index 024a103..1d6ac9e 100644 --- a/src/Gui/ConfBackend.py +++ b/src/Gui/ConfBackend.py @@ -1,5 +1,8 @@ from abrt_utils import _ +# Doc on Gnome keyring API: +# http://library.gnome.org/devel/gnome-keyring/stable/ + #FIXME: add some backend factory try: -- cgit From ccadc8322d61b660fa65458a5ae2721a2b2cea59 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Thu, 14 Jan 2010 13:00:06 +0100 Subject: don't use getpagesize, it has been removed from posix --- lib/Plugins/KerneloopsScanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp index 2d4499f..1bb45ab 100644 --- a/lib/Plugins/KerneloopsScanner.cpp +++ b/lib/Plugins/KerneloopsScanner.cpp @@ -122,7 +122,7 @@ int CKerneloopsScanner::ScanDmesg() int cnt_FoundOopses; char *buffer; - int pagesz = getpagesize(); + long pagesz = sysconf(_SC_PAGESIZE); buffer = (char*)xzalloc(pagesz + 1); -- cgit From 8d51d37a4a330a0574ebe11d37bce3abadea3162 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 14 Jan 2010 16:11:13 +0100 Subject: GUI: make it so that even non-loaded plugins show up in "Plugins" dialog Signed-off-by: Denys Vlasenko --- src/CLI/dbus.cpp | 6 ++- src/CLI/dbus.h | 6 ++- src/Daemon/CommLayerServerDBus.cpp | 10 ++-- src/Daemon/Daemon.cpp | 3 +- src/Daemon/PluginManager.cpp | 96 +++++++++++++++++++------------------- src/Daemon/PluginManager.h | 13 ++++-- src/Gui/ABRTPlugin.py | 3 +- src/Gui/CCDBusBackend.py | 2 - src/Gui/CCDumpList.py | 2 - src/Gui/PluginList.py | 17 +++---- 10 files changed, 80 insertions(+), 78 deletions(-) diff --git a/src/CLI/dbus.cpp b/src/CLI/dbus.cpp index b218679..0d03c4d 100644 --- a/src/CLI/dbus.cpp +++ b/src/CLI/dbus.cpp @@ -184,7 +184,8 @@ int32_t call_DeleteDebugDump(const char* uuid) return result; } -vector_map_string_t call_GetPluginsInfo() +#ifdef UNUSED +map_map_string_t call_GetPluginsInfo() { DBusMessage *msg = new_call_msg(__func__ + 5); DBusMessage *reply = send_get_reply_and_unref(msg); @@ -192,7 +193,7 @@ vector_map_string_t call_GetPluginsInfo() DBusMessageIter in_iter; dbus_message_iter_init(reply, &in_iter); - vector_map_string_t argout; + map_map_string_t argout; int r = load_val(&in_iter, argout); if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); @@ -200,6 +201,7 @@ vector_map_string_t call_GetPluginsInfo() dbus_message_unref(reply); return argout; } +#endif void handle_dbus_err(bool error_flag, DBusError *err) { diff --git a/src/CLI/dbus.h b/src/CLI/dbus.h index 3c157c0..c692e19 100644 --- a/src/CLI/dbus.h +++ b/src/CLI/dbus.h @@ -28,15 +28,17 @@ map_crash_report_t call_CreateReport(const char *uuid); report_status_t call_Report(const map_crash_report_t& report); int32_t call_DeleteDebugDump(const char* uuid); +#ifdef UNUSED /* Gets basic data about all installed plugins. */ -vector_map_string_t call_GetPluginsInfo(); +map_map_string_t call_GetPluginsInfo(); /** Gets default plugin settings. * @param name - * Corresponds to name obtained from call_GetPluginsInfo. + * Corresponds to name obtained from call_GetPluginsInfo. */ map_plugin_settings_t call_GetPluginSettings(const char *name); +#endif void handle_dbus_err(bool error_flag, DBusError *err); diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index 8589941..db0d2f5 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -325,11 +325,9 @@ static int handle_DeleteDebugDump(DBusMessage* call, DBusMessage* reply) static int handle_GetPluginsInfo(DBusMessage* call, DBusMessage* reply) { - vector_map_string_t plugins_info = g_pPluginManager->GetPluginsInfo(); - DBusMessageIter out_iter; dbus_message_iter_init_append(reply, &out_iter); - store_val(&out_iter, plugins_info); + store_val(&out_iter, g_pPluginManager->GetPluginsInfo()); send_flush_and_unref(reply); return 0; @@ -348,9 +346,9 @@ static int handle_GetPluginSettings(DBusMessage* call, DBusMessage* reply) return -1; } - long unix_uid = get_remote_uid(call); - VERB1 log("got %s('%s') call from uid %ld", "GetPluginSettings", PluginName, unix_uid); - map_plugin_settings_t plugin_settings = g_pPluginManager->GetPluginSettings(PluginName, to_string(unix_uid).c_str()); + //long unix_uid = get_remote_uid(call); + //VERB1 log("got %s('%s') call from uid %ld", "GetPluginSettings", PluginName, unix_uid); + map_plugin_settings_t plugin_settings = g_pPluginManager->GetPluginSettings(PluginName); //, to_string(unix_uid).c_str()); DBusMessageIter out_iter; dbus_message_iter_init_append(reply, &out_iter); diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 09d8ab8..a2970af 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -65,7 +65,8 @@ * Returns report_status_t (map_vector_string_t) - the status of each call. * 2nd parameter is the contents of user's abrt.conf. * - DeleteDebugDump(UUID): delete it from DB and delete corresponding /var/cache/abrt/DIR - * - GetPluginsInfo(): returns vector_map_string_t + * - GetPluginsInfo(): returns map_map_string_t + * map["plugin"] = { "Name": "plugin", "Enabled": "yes" ... } * - GetPluginSettings(PluginName): returns map_plugin_settings_t (map_string_t) * - SetPluginSettings(PluginName, map_plugin_settings_t): returns void * - RegisterPlugin(PluginName): returns void diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp index 136277c..c552880 100644 --- a/src/Daemon/PluginManager.cpp +++ b/src/Daemon/PluginManager.cpp @@ -27,6 +27,8 @@ #include "Polkit.h" #include "PluginManager.h" +using namespace std; + /** * Text representation of plugin types. */ @@ -40,12 +42,12 @@ static const char *const plugin_type_str[] = { bool LoadPluginSettings(const char *pPath, map_plugin_settings_t& pSettings) { - std::ifstream fIn; + ifstream fIn; fIn.open(pPath); if (!fIn.is_open()) return false; - std::string line; + string line; while (!fIn.eof()) { getline(fIn, line); @@ -54,8 +56,8 @@ bool LoadPluginSettings(const char *pPath, map_plugin_settings_t& pSettings) bool is_value = false; bool valid = false; bool in_quote = false; - std::string key; - std::string value; + string key; + string value; for (ii = 0; ii < line.length(); ii++) { if (line[ii] == '"') @@ -157,6 +159,10 @@ void CPluginManager::UnLoadPlugins() CPlugin* CPluginManager::LoadPlugin(const char *pName, bool enabled_only) { + map_string_t plugin_info; + + plugin_info["Name"] = pName; + map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); if (it_plugin != m_mapPlugins.end()) { @@ -170,8 +176,9 @@ CPlugin* CPluginManager::LoadPlugin(const char *pName, bool enabled_only) conf_name = "Kerneloops"; } map_plugin_settings_t pluginSettings; - std::string conf_fullname = ssprintf(PLUGINS_CONF_DIR"/%s."PLUGINS_CONF_EXTENSION, conf_name); + string conf_fullname = ssprintf(PLUGINS_CONF_DIR"/%s."PLUGINS_CONF_EXTENSION, conf_name); LoadPluginSettings(conf_fullname.c_str(), pluginSettings); + m_map_plugin_settings[pName] = pluginSettings; VERB3 log("Loaded %s.conf", conf_name); if (enabled_only) @@ -179,12 +186,21 @@ CPlugin* CPluginManager::LoadPlugin(const char *pName, bool enabled_only) map_plugin_settings_t::iterator it = pluginSettings.find("Enabled"); if (it == pluginSettings.end() || !string_to_bool(it->second.c_str())) { + plugin_info["Enabled"] = "no"; + string empty; + plugin_info["Type"] = empty; + plugin_info["Version"] = empty; + plugin_info["Description"] = empty; + plugin_info["Email"] = empty; + plugin_info["WWW"] = empty; + plugin_info["GTKBuilder"] = empty; + m_map_plugin_info[pName] = plugin_info; VERB3 log("Plugin %s: 'Enabled' is not set, not loading it (yet)", pName); return NULL; /* error */ } } - std::string libPath = ssprintf(PLUGINS_LIB_DIR"/"PLUGINS_LIB_PREFIX"%s."PLUGINS_LIB_EXTENSION, pName); + string libPath = ssprintf(PLUGINS_LIB_DIR"/"PLUGINS_LIB_PREFIX"%s."PLUGINS_LIB_EXTENSION, pName); CLoadedModule* module = new CLoadedModule(libPath.c_str()); if (module->GetMagicNumber() != PLUGINS_MAGIC_NUMBER || module->GetType() < 0 @@ -217,6 +233,16 @@ CPlugin* CPluginManager::LoadPlugin(const char *pName, bool enabled_only) return NULL; /* error */ } + plugin_info["Enabled"] = "yes"; + plugin_info["Type"] = plugin_type_str[module->GetType()]; + //plugin_info["Name"] = module->GetName(); + plugin_info["Version"] = module->GetVersion(); + plugin_info["Description"] = module->GetDescription(); + plugin_info["Email"] = module->GetEmail(); + plugin_info["WWW"] = module->GetWWW(); + plugin_info["GTKBuilder"] = module->GetGTKBuilder(); + + m_map_plugin_info[pName] = plugin_info; m_mapLoadedModules[pName] = module; m_mapPlugins[pName] = plugin; log("Registered %s plugin '%s'", plugin_type_str[module->GetType()], pName); @@ -344,28 +370,6 @@ plugin_type_t CPluginManager::GetPluginType(const char *pName) return it_module->second->GetType(); } -vector_map_string_t CPluginManager::GetPluginsInfo() -{ - vector_map_string_t ret; - map_loaded_module_t::iterator it_module = m_mapLoadedModules.begin(); - for (; it_module != m_mapLoadedModules.end(); it_module++) - { - map_string_t plugin_info; - - plugin_info["Enabled"] = (m_mapPlugins.find(it_module->second->GetName()) != m_mapPlugins.end()) ? - "yes" : "no"; - plugin_info["Type"] = plugin_type_str[it_module->second->GetType()]; - plugin_info["Name"] = it_module->second->GetName(); - plugin_info["Version"] = it_module->second->GetVersion(); - plugin_info["Description"] = it_module->second->GetDescription(); - plugin_info["Email"] = it_module->second->GetEmail(); - plugin_info["WWW"] = it_module->second->GetWWW(); - plugin_info["GTKBuilder"] = it_module->second->GetGTKBuilder(); - ret.push_back(plugin_info); - } - return ret; -} - void CPluginManager::SetPluginSettings(const char *pName, const char *pUID, const map_plugin_settings_t& pSettings) @@ -388,14 +392,14 @@ void CPluginManager::SetPluginSettings(const char *pName, return; } - std::string home = get_home_dir(xatoi_u(pUID.c_str())); + string home = get_home_dir(xatoi_u(pUID.c_str())); if (home == "") { return; } - std::string confDir = home + "/.abrt"; - std::string confPath = confDir + "/" + pName + "."PLUGINS_CONF_EXTENSION; + string confDir = home + "/.abrt"; + string confPath = confDir + "/" + pName + "."PLUGINS_CONF_EXTENSION; uid_t uid = xatoi_u(pUID.c_str()); struct passwd* pw = getpwuid(uid); gid_t gid = pw ? pw->pw_gid : uid; @@ -440,33 +444,31 @@ void CPluginManager::SetPluginSettings(const char *pName, #endif } -map_plugin_settings_t CPluginManager::GetPluginSettings(const char *pName, - const char *pUID) +map_plugin_settings_t CPluginManager::GetPluginSettings(const char *pName) { map_plugin_settings_t ret; + map_loaded_module_t::iterator it_module = m_mapLoadedModules.find(pName); if (it_module != m_mapLoadedModules.end()) { map_plugin_t::iterator it_plugin = m_mapPlugins.find(pName); if (it_plugin != m_mapPlugins.end()) { + VERB3 log("Returning settings for loaded plugin %s", pName); ret = it_plugin->second->GetSettings(); - /** we don't want to load it from daemon if it's running under root - but wi might get back to this once we make the daemon to not run - with root privileges - */ - /* - if (it_module->second->GetType() == REPORTER) - { - std::string home = get_home_dir(xatoi_u(pUID.c_str())); - if (home != "") - { - LoadPluginSettings(home + "/.abrt/" + pName + "."PLUGINS_CONF_EXTENSION, ret); - } - } - */ return ret; } } + /* else: module is not loaded */ + map_map_string_t::iterator it_settings = m_map_plugin_settings.find(pName); + if (it_settings != m_map_plugin_settings.end()) + { + /* but it exists, its settings are available nevertheless */ + VERB3 log("Returning settings for non-loaded plugin %s", pName); + ret = it_settings->second; + return ret; + } + + VERB3 log("Request for settings of unknown plugin %s, returning null result", pName); return ret; } diff --git a/src/Daemon/PluginManager.h b/src/Daemon/PluginManager.h index d3e686c..22cc387 100644 --- a/src/Daemon/PluginManager.h +++ b/src/Daemon/PluginManager.h @@ -50,6 +50,11 @@ class CPluginManager * Registered plugins. A key is a plugin name. */ map_plugin_t m_mapPlugins; + /** + * List of all possible plugins (loaded or not), with some attributes. + */ + map_map_string_t m_map_plugin_info; + map_map_string_t m_map_plugin_settings; public: /** @@ -130,7 +135,7 @@ class CPluginManager * Then user can fill all needed informations like URLs etc. * @return A vector of maps */ - vector_map_string_t GetPluginsInfo(); + const map_map_string_t& GetPluginsInfo() { return m_map_plugin_info; } /** * A method, which sets up a plugin. The settings are also saved in home * directory of an user. @@ -144,11 +149,9 @@ class CPluginManager /** * A method, which returns plugin's settings according to user. * @param pName A plugin name. - * @param pUID An uid of user. - * @return Plugin's settings accorting to user. + * @return Plugin's settings. */ - map_plugin_settings_t GetPluginSettings(const char *pName, - const char *pUID); + map_plugin_settings_t GetPluginSettings(const char *pName); }; /** diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py index 03b61fb..9f66a83 100644 --- a/src/Gui/ABRTPlugin.py +++ b/src/Gui/ABRTPlugin.py @@ -53,7 +53,8 @@ class PluginSettings(dict): class PluginInfo(): """Class to represent common plugin info""" - types = {"Analyzer":_("Analyzer plugins"), + types = {"":_("Not loaded plugins"), + "Analyzer":_("Analyzer plugins"), "Action":_("Action plugins"), "Reporter":_("Reporter plugins"), "Database":_("Database plugins")} diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py index ac378f4..64deb39 100644 --- a/src/Gui/CCDBusBackend.py +++ b/src/Gui/CCDBusBackend.py @@ -191,8 +191,6 @@ class DBusManager(gobject.GObject): def getPluginSettings(self, plugin_name): settings = self.daemon().GetPluginSettings(plugin_name) - #for i in settings.keys(): - # print i return settings # "Enable" toggling in GUI is disabled for now. Grep for PLUGIN_DYNAMIC_LOAD_UNLOAD diff --git a/src/Gui/CCDumpList.py b/src/Gui/CCDumpList.py index 09191f5..a8657e0 100644 --- a/src/Gui/CCDumpList.py +++ b/src/Gui/CCDumpList.py @@ -6,7 +6,6 @@ class DumpList(list): """Class to store list of debug dumps""" def __init__(self,dbus_manager=None): self.dm = dbus_manager - self.ddict = {} def load(self): if self.dm: @@ -21,7 +20,6 @@ class DumpList(list): # print "DumpList adding %s:%s" % (column,row[column]) entry.__dict__[column] = row[column] self.append(entry) - self.ddict[entry.getUUID()] = entry except Exception, e: # FIXME handle exception better # this is just temporary workaround for rhbz#543725 diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py index 79df126..6db603e 100644 --- a/src/Gui/PluginList.py +++ b/src/Gui/PluginList.py @@ -6,24 +6,21 @@ class PluginInfoList(list): """Class to store list of PluginInfos""" def __init__(self,dbus_manager=None): self.dm = dbus_manager - self.ddict = {} def load(self): if self.dm: #print "loading PluginList" rows = self.dm.getPluginsInfo() #print rows - for row in rows: + for plugin_name in rows: + row = rows[plugin_name] entry = PluginInfo() - for column in row: - #print "PluginInfoList adding %s:%s" % (column,row[column]) - entry.__dict__[column] = row[column] - if entry.Enabled == "yes": - #entry.Settings = PluginSettings(self.dm.getPluginSettings(str(entry))) - daemon_settings = self.dm.getPluginSettings(str(entry)) - entry.load_daemon_settings(daemon_settings) + for attr_name in row: + print "PluginInfoList adding %s[%s]:%s" % (plugin_name, attr_name, row[attr_name]) + entry.__dict__[attr_name] = row[attr_name] + daemon_settings = self.dm.getPluginSettings(plugin_name) + entry.load_daemon_settings(daemon_settings) self.append(entry) - self.ddict[entry.getName()] = entry else: print "db == None!" -- cgit From ab4aa70e27cd66c7b2f3f530cfb6f026322eb91c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 14 Jan 2010 16:13:04 +0100 Subject: comment out forgotten debugging Signed-off-by: Denys Vlasenko --- src/Gui/PluginList.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py index 6db603e..50a4067 100644 --- a/src/Gui/PluginList.py +++ b/src/Gui/PluginList.py @@ -16,7 +16,7 @@ class PluginInfoList(list): row = rows[plugin_name] entry = PluginInfo() for attr_name in row: - print "PluginInfoList adding %s[%s]:%s" % (plugin_name, attr_name, row[attr_name]) + #print "PluginInfoList adding %s[%s]:%s" % (plugin_name, attr_name, row[attr_name]) entry.__dict__[attr_name] = row[attr_name] daemon_settings = self.dm.getPluginSettings(plugin_name) entry.load_daemon_settings(daemon_settings) -- cgit From 2a8dfdad5a5e4ccb0c7a2e9147c38336ba76d733 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 14 Jan 2010 17:47:01 +0100 Subject: gui: add logging infrastructure Signed-off-by: Denys Vlasenko --- src/Gui/ABRTExceptions.py | 2 +- src/Gui/ABRTPlugin.py | 5 ++--- src/Gui/CCDBusBackend.py | 20 +++++++++---------- src/Gui/CCMainWindow.py | 26 +++++++++++++++++------- src/Gui/CCReporterDialog.py | 2 +- src/Gui/CC_gui_functions.py | 20 ++++++++++--------- src/Gui/ConfBackend.py | 2 +- src/Gui/PluginList.py | 7 +++---- src/Gui/PluginSettingsUI.py | 2 +- src/Gui/PluginsSettingsDialog.py | 17 +++++++++++----- src/Gui/SettingsDialog.py | 2 +- src/Gui/abrt_utils.py | 43 ++++++++++++++++++++++++++++++---------- 12 files changed, 94 insertions(+), 54 deletions(-) diff --git a/src/Gui/ABRTExceptions.py b/src/Gui/ABRTExceptions.py index c4d6b59..c857f71 100644 --- a/src/Gui/ABRTExceptions.py +++ b/src/Gui/ABRTExceptions.py @@ -1,4 +1,4 @@ -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 class IsRunning(Exception): def __init__(self): diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py index 9f66a83..5fb551d 100644 --- a/src/Gui/ABRTPlugin.py +++ b/src/Gui/ABRTPlugin.py @@ -10,7 +10,7 @@ Type Email Description """ -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError class PluginSettings(dict): @@ -63,7 +63,6 @@ class PluginInfo(): "Type", "Email", "Description"] def __init__(self): - #print "Init PluginInfo" self.WWW = None self.Name = None self.Enabled = None @@ -96,7 +95,7 @@ class PluginInfo(): if self.Name: self.Settings.load_daemon_settings(self.Name, daemon_settings) else: - print _("Plugin name is not set, can't load its settings") + log("Plugin name is not set, can't load its settings") def save_settings_on_client_side(self): self.Settings.save_on_client_side(str(self.Name)) diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py index 64deb39..1ec2d8a 100644 --- a/src/Gui/CCDBusBackend.py +++ b/src/Gui/CCDBusBackend.py @@ -6,7 +6,7 @@ from dbus.mainloop.glib import DBusGMainLoop import gtk from dbus.exceptions import * import ABRTExceptions -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 CC_NAME = 'com.redhat.abrt' CC_IFACE = 'com.redhat.abrt' @@ -111,13 +111,13 @@ class DBusManager(gobject.GObject): # def disconnected(self, *args): # print "disconnect" - def error_handler_cb(self,error): - self.emit("abrt-error",error) + def error_handler_cb(self, error): + self.emit("abrt-error", error) - def warning_handler_cb(self,arg): - self.emit("warning",arg) + def warning_handler_cb(self, arg): + self.emit("warning", arg) - def error_handler(self,arg): + def error_handler(self, arg): # used to silently ingore dbus timeouts pass @@ -134,11 +134,11 @@ class DBusManager(gobject.GObject): self.emit("crash") def update_cb(self, message, job_id=0): - print "Update >>%s<<" % message + log1("Update:%s", message) self.emit("update", message) def warning_cb(self, message, job_id=0): - print "Warning >>%s<<" % message + log1("Warning:%s", message) self.emit("warning", message) def owner_changed_cb(self,name, old_owner, new_owner): @@ -151,7 +151,7 @@ class DBusManager(gobject.GObject): def jobdone_cb(self, dest, uuid): # TODO: check that it is indeed OUR job: # remember uuid in getReport and compare here - print "Our job for UUID %s is done." % uuid + log1("Our job for UUID %s is done", uuid) dump = self.daemon().CreateReport(uuid) if dump: self.emit("analyze-complete", dump) @@ -208,6 +208,6 @@ class DBusManager(gobject.GObject): def setSettings(self, settings): # FIXME: STUB!!!! - print "setSettings stub" + log1("setSettings stub") retval = self.daemon().SetSettings(self.daemon().GetSettings()) print ">>>", retval diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py index f4e3a73..432fd43 100644 --- a/src/Gui/CCMainWindow.py +++ b/src/Gui/CCMainWindow.py @@ -2,6 +2,7 @@ import sys import os import pwd +import getopt import pygtk pygtk.require("2.0") import gobject @@ -12,6 +13,11 @@ except RuntimeError,e: print e os.exit() import gtk.glade +try: + import rpm +except Exception, ex: + rpm = None + import CCDBusBackend from CC_gui_functions import * from CCDumpList import getDumpList, DumpList @@ -21,12 +27,7 @@ from SettingsDialog import SettingsDialog from CCReport import Report from PluginList import getPluginInfoList import ABRTExceptions -from abrt_utils import _ - -try: - import rpm -except Exception, ex: - rpm = None +from abrt_utils import _, init_logging, log, log1, log2 class MainWindow(): @@ -381,8 +382,19 @@ class MainWindow(): self.window.present() if __name__ == "__main__": + try: + opts, args = getopt.getopt(sys.argv[1:], "v") + except getopt.GetoptError, err: + print str(err) # prints something like "option -a not recognized" + sys.exit(2) + verbose = 0 + for opt, arg in opts: + if opt == "-v": + verbose += 1 + init_logging("abrt-gui", verbose) + log1("log level:%d", verbose) + cc = MainWindow() cc.hydrate() cc.show() gtk.main() - diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py index bba8942..ab6ad0f 100644 --- a/src/Gui/CCReporterDialog.py +++ b/src/Gui/CCReporterDialog.py @@ -12,7 +12,7 @@ from ABRTPlugin import PluginInfo from PluginSettingsUI import PluginSettingsUI from PluginList import getPluginInfoList #from CCDumpList import getDumpList, DumpList -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 # FIXME - create method or smth that returns type|editable|content CD_TYPE = 0 diff --git a/src/Gui/CC_gui_functions.py b/src/Gui/CC_gui_functions.py index 0532ab7..0379f20 100644 --- a/src/Gui/CC_gui_functions.py +++ b/src/Gui/CC_gui_functions.py @@ -15,13 +15,15 @@ try: import rpm except: rpm = None +from abrt_utils import _, log, log1, log2 + def on_url_clicked(label, url): import gnomevfs file_mimetype = gnomevfs.get_mime_type(url) default_app = gnomevfs.mime_get_default_application(file_mimetype) if default_app: - #print "Default Application:", default_app[2] + log2("default application:%s", default_app[2]) subprocess.Popen([default_app[2], url]) def gui_report_dialog ( report_status_dict, parent_dialog, @@ -160,8 +162,8 @@ def gui_question_dialog ( message, parent_dialog=None, dialog.destroy() return ret -def get_icon_for_package(theme,package): - #print package +def get_icon_for_package(theme, package): + log2("get_icon_for_package('%s')", package) try: return theme.load_icon(package, 22, gtk.ICON_LOOKUP_USE_BUILTIN) except: @@ -169,7 +171,7 @@ def get_icon_for_package(theme,package): if not rpm: return None ts = rpm.TransactionSet() - mi = ts.dbMatch( 'name', package ) + mi = ts.dbMatch('name', package) possible_icons = [] icon_filename = "" filenames = "" @@ -180,19 +182,19 @@ def get_icon_for_package(theme,package): if filename.rfind(".png") != -1: possible_icons.append(filename) if filename.rfind(".desktop") != -1: - #print filename + log2("desktop file:'%s'", filename) desktop_file = open(filename, 'r') lines = desktop_file.readlines() for line in lines: if line.find("Icon=") != -1: - #print line[5:-1] + log2("Icon='%s'", line[5:-1]) icon_filename = line[5:-1] break desktop_file.close() # .dektop file found for filename in h['filenames']: if filename.rfind("%s.png" % icon_filename) != -1: - #print filename + log2("png file:'%s'", filename) icon_filename = filename break #we didn't find the .desktop file @@ -205,8 +207,8 @@ def get_icon_for_package(theme,package): if icon_filename: break if icon_filename: - #print "icon created form %s" % icon_filename - return gtk.gdk.pixbuf_new_from_file_at_size(icon_filename,22,22) + log1("icon created from %s", icon_filename) + return gtk.gdk.pixbuf_new_from_file_at_size(icon_filename, 22, 22) else: return None diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py index 1d6ac9e..08ceed5 100644 --- a/src/Gui/ConfBackend.py +++ b/src/Gui/ConfBackend.py @@ -1,4 +1,4 @@ -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 # Doc on Gnome keyring API: # http://library.gnome.org/devel/gnome-keyring/stable/ diff --git a/src/Gui/PluginList.py b/src/Gui/PluginList.py index 50a4067..d2232bb 100644 --- a/src/Gui/PluginList.py +++ b/src/Gui/PluginList.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import CCDBusBackend from ABRTPlugin import PluginInfo, PluginSettings +from abrt_utils import _, log, log1, log2 class PluginInfoList(list): """Class to store list of PluginInfos""" @@ -9,20 +10,18 @@ class PluginInfoList(list): def load(self): if self.dm: - #print "loading PluginList" rows = self.dm.getPluginsInfo() - #print rows for plugin_name in rows: row = rows[plugin_name] entry = PluginInfo() for attr_name in row: - #print "PluginInfoList adding %s[%s]:%s" % (plugin_name, attr_name, row[attr_name]) + log2("PluginInfoList: adding %s[%s]:%s", plugin_name, attr_name, row[attr_name]) entry.__dict__[attr_name] = row[attr_name] daemon_settings = self.dm.getPluginSettings(plugin_name) entry.load_daemon_settings(daemon_settings) self.append(entry) else: - print "db == None!" + log("PluginInfoList: db == None") def getEnabledPlugins(self): return [x for x in self if x["Enabled"] == 'yes'] diff --git a/src/Gui/PluginSettingsUI.py b/src/Gui/PluginSettingsUI.py index a26f87f..c324b31 100644 --- a/src/Gui/PluginSettingsUI.py +++ b/src/Gui/PluginSettingsUI.py @@ -1,5 +1,5 @@ import gtk -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 class PluginSettingsUI(gtk.Dialog): def __init__(self, pluginfo, parent=None): diff --git a/src/Gui/PluginsSettingsDialog.py b/src/Gui/PluginsSettingsDialog.py index 0d41962..611a8c5 100644 --- a/src/Gui/PluginsSettingsDialog.py +++ b/src/Gui/PluginsSettingsDialog.py @@ -4,7 +4,7 @@ from PluginList import getPluginInfoList, PluginInfoList from CC_gui_functions import * from PluginSettingsUI import PluginSettingsUI from ABRTPlugin import PluginSettings, PluginInfo -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 class PluginsSettingsDialog: @@ -13,7 +13,7 @@ class PluginsSettingsDialog: self.ccdaemon = daemon self.builder = gtk.Builder() - builderfile = "%s%ssettings.glade" % (sys.path[0],"/") + builderfile = "%s%ssettings.glade" % (sys.path[0], "/") #print builderfile try: self.builder.add_from_file(builderfile) @@ -99,13 +99,20 @@ class PluginsSettingsDialog: except Exception, e: print e #gui_error_message("Error while loading plugins info, please check if abrt daemon is running\n %s" % e) + return plugin_rows = {} for plugin_type in PluginInfo.types.keys(): - it = self.pluginsListStore.append(None, ["%s" % PluginInfo.types[plugin_type], 0, 0, 1, "gray", None]) + it = self.pluginsListStore.append(None, + ["%s" % PluginInfo.types[plugin_type], 0, 0, 1, "gray", None]) plugin_rows[plugin_type] = it for entry in pluginlist: + if entry.Description: + text = "%s\n%s" % (entry.getName(), entry.Description) + else: + # non-loaded plugins have empty description + text = "%s" % entry.getName() self.pluginsListStore.append(plugin_rows[entry.getType()], - ["%s\n%s" % (entry.getName(), entry.Description), entry.Enabled == "yes", 1, 0, "white", entry]) + [text, entry.Enabled == "yes", 1, 0, "white", entry]) self.pluginlist.expand_all() def dehydrate(self): @@ -149,7 +156,7 @@ class PluginsSettingsDialog: elif response == gtk.RESPONSE_CANCEL: pass else: - print _("unknown response from settings dialog") + log("unknown response from settings dialog:%d", response) ui.destroy() def on_bClose_clicked(self, button): diff --git a/src/Gui/SettingsDialog.py b/src/Gui/SettingsDialog.py index c2b292f..893c23f 100644 --- a/src/Gui/SettingsDialog.py +++ b/src/Gui/SettingsDialog.py @@ -3,7 +3,7 @@ import gtk from PluginList import getPluginInfoList from CC_gui_functions import * #from PluginSettingsUI import PluginSettingsUI -from abrt_utils import _ +from abrt_utils import _, log, log1, log2 #FIXME: create a better struct, to automatize hydrate/dehydrate process diff --git a/src/Gui/abrt_utils.py b/src/Gui/abrt_utils.py index 6122b9c..2fabb54 100644 --- a/src/Gui/abrt_utils.py +++ b/src/Gui/abrt_utils.py @@ -1,16 +1,37 @@ +import sys import gtk.glade + PROGNAME = "abrt" +g_verbose = 0 + import locale -try: - locale.setlocale (locale.LC_ALL, "") -except locale.Error, e: - import os - os.environ['LC_ALL'] = 'C' - locale.setlocale (locale.LC_ALL, "") import gettext -gettext.bind_textdomain_codeset(PROGNAME,locale.nl_langinfo(locale.CODESET)) -gettext.bindtextdomain(PROGNAME, '/usr/share/locale') -gtk.glade.bindtextdomain(PROGNAME, '/usr/share/locale') -gtk.glade.textdomain(PROGNAME) -gettext.textdomain(PROGNAME) + _ = lambda x: gettext.lgettext(x) + +def init_logging(progname, v): + global PROGNAME, g_verbose + PROGNAME = progname + g_verbose = v + try: + locale.setlocale(locale.LC_ALL, "") + except locale.Error, e: + import os + os.environ['LC_ALL'] = 'C' + locale.setlocale(locale.LC_ALL, "") + gettext.bind_textdomain_codeset(PROGNAME, locale.nl_langinfo(locale.CODESET)) + gettext.bindtextdomain(PROGNAME, '/usr/share/locale') + gtk.glade.bindtextdomain(PROGNAME, '/usr/share/locale') + gtk.glade.textdomain(PROGNAME) + gettext.textdomain(PROGNAME) + +def log(fmt, *args): + sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args)) + +def log1(fmt, *args): + if g_verbose >= 1: + sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args)) + +def log2(fmt, *args): + if g_verbose >= 2: + sys.stderr.write("%s: %s\n" % (PROGNAME, fmt % args)) -- cgit From c255478c17fca74e8e31aa99321eb63b7b1ecc7d Mon Sep 17 00:00:00 2001 From: warrink Date: Thu, 14 Jan 2010 16:52:03 +0000 Subject: Sending translation for Dutch --- po/nl.po | 90 +++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/po/nl.po b/po/nl.po index d1db543..c66b3bd 100644 --- a/po/nl.po +++ b/po/nl.po @@ -6,14 +6,14 @@ # # Geert Warrink , 2009. # Richard van der Luit , 2009. -# Geert Warrink , 2009. +# Geert Warrink , 2009, 2010. #: ../src/Gui/CCReporterDialog.py:208 msgid "" msgstr "" "Project-Id-Version: abrt.master\n" "Report-Msgid-Bugs-To: jmoskovc@redhat.com\n" -"POT-Creation-Date: 2009-12-15 16:54+0000\n" -"PO-Revision-Date: 2009-12-15 18:05+0100\n" +"POT-Creation-Date: 2010-01-14 15:35+0000\n" +"PO-Revision-Date: 2010-01-14 17:50+0100\n" "Last-Translator: Geert Warrink \n" "Language-Team: nl \n" "MIME-Version: 1.0\n" @@ -31,23 +31,27 @@ msgid "Got unexpected data from daemon (is the database properly updated?)." msgstr "" "Kreeg niet verwachte data van daemon (is de database correct vernieuwd?)." -#: ../src/Gui/ABRTPlugin.py:55 +#: ../src/Gui/ABRTPlugin.py:56 +msgid "Not loaded plugins" +msgstr "Niet geladen plugins" + +#: ../src/Gui/ABRTPlugin.py:57 msgid "Analyzer plugins" msgstr "Analyse plugins" -#: ../src/Gui/ABRTPlugin.py:56 +#: ../src/Gui/ABRTPlugin.py:58 msgid "Action plugins" msgstr "Actie plugins" -#: ../src/Gui/ABRTPlugin.py:57 +#: ../src/Gui/ABRTPlugin.py:59 msgid "Reporter plugins" msgstr "Rapporteer plugins" -#: ../src/Gui/ABRTPlugin.py:58 +#: ../src/Gui/ABRTPlugin.py:60 msgid "Database plugins" msgstr "Databse plugins" -#: ../src/Gui/ABRTPlugin.py:97 +#: ../src/Gui/ABRTPlugin.py:99 msgid "Plugin name is not set, can't load its settings" msgstr "Plugin naam is niet ingesteld, kan zijn instellingen niet laden" @@ -144,31 +148,31 @@ msgid "_Help" msgstr "_Hulp" #. add pixbuff separatelly -#: ../src/Gui/CCMainWindow.py:71 +#: ../src/Gui/CCMainWindow.py:76 msgid "Icon" msgstr "Icoon" -#: ../src/Gui/CCMainWindow.py:79 +#: ../src/Gui/CCMainWindow.py:84 msgid "Package" msgstr "Pakket" -#: ../src/Gui/CCMainWindow.py:80 +#: ../src/Gui/CCMainWindow.py:85 msgid "Application" msgstr "Toepassing" -#: ../src/Gui/CCMainWindow.py:81 +#: ../src/Gui/CCMainWindow.py:86 msgid "Date" msgstr "Datum" -#: ../src/Gui/CCMainWindow.py:82 +#: ../src/Gui/CCMainWindow.py:87 msgid "Crash count" msgstr "Crash count" -#: ../src/Gui/CCMainWindow.py:83 +#: ../src/Gui/CCMainWindow.py:88 msgid "User" msgstr "Gebruiker" -#: ../src/Gui/CCMainWindow.py:149 +#: ../src/Gui/CCMainWindow.py:156 #, python-format msgid "" "Can't show the settings dialog\n" @@ -177,7 +181,7 @@ msgstr "" "Kan de instellingen dialoog niet tonen\n" "%s" -#: ../src/Gui/CCMainWindow.py:160 +#: ../src/Gui/CCMainWindow.py:167 #, python-format msgid "" "Unable to finish current task!\n" @@ -187,7 +191,7 @@ msgstr "" "%s" #. there is something wrong with the daemon if we cant get the dumplist -#: ../src/Gui/CCMainWindow.py:187 +#: ../src/Gui/CCMainWindow.py:194 #, python-format msgid "" "Error while loading the dumplist.\n" @@ -196,15 +200,15 @@ msgstr "" "Fout tijdens het laden van de dumplijst.\n" "%s" -#: ../src/Gui/CCMainWindow.py:224 +#: ../src/Gui/CCMainWindow.py:231 msgid "This crash has been reported:\n" msgstr "Deze crash is gerapporteerd:\n" -#: ../src/Gui/CCMainWindow.py:234 +#: ../src/Gui/CCMainWindow.py:241 msgid "Not reported!" msgstr "Niet gerapporteerd!" -#: ../src/Gui/CCMainWindow.py:283 +#: ../src/Gui/CCMainWindow.py:290 msgid "" "Unable to get report!\n" "Debuginfo is missing?" @@ -212,7 +216,7 @@ msgstr "" "Kan geen rapport krijgen!\n" "Mist debuginfo?" -#: ../src/Gui/CCMainWindow.py:302 +#: ../src/Gui/CCMainWindow.py:309 #, python-format msgid "" "Reporting failed!\n" @@ -221,7 +225,7 @@ msgstr "" "Rapporteren mislukte!\n" "%s" -#: ../src/Gui/CCMainWindow.py:321 ../src/Gui/CCMainWindow.py:348 +#: ../src/Gui/CCMainWindow.py:328 ../src/Gui/CCMainWindow.py:355 #, python-format msgid "Error getting the report: %s" msgstr "Fout tijdens het verkrijgen van het rapport: %s" @@ -446,11 +450,11 @@ msgstr "Een crash in pakket %s is ontdekt" msgid "ABRT service is not running" msgstr "ABRT service draait niet" -#: ../src/Applet/CCApplet.cpp:196 +#: ../src/Applet/CCApplet.cpp:200 msgid "Warning" msgstr "Waarschuwing" -#: ../src/Daemon/Daemon.cpp:473 +#: ../src/Daemon/Daemon.cpp:474 msgid "" "Report size exceeded the quota. Please check system's MaxCrashReportsSize " "value in abrt.conf." @@ -458,37 +462,37 @@ msgstr "" "Rapport grootte overschreed quota. Controleer a.u.b. MaxCrashReportsSize " "waarde van het systeem in abrt.conf." -#: ../lib/Plugins/Bugzilla.cpp:202 +#: ../lib/Plugins/Bugzilla.cpp:265 #, c-format msgid "Bug is already reported: %i" msgstr "Bug is al aangemeld: %i" -#: ../lib/Plugins/Bugzilla.cpp:264 +#: ../lib/Plugins/Bugzilla.cpp:341 #, c-format msgid "New bug id: %i" msgstr "Nieuwe bug id: %i" -#: ../lib/Plugins/Bugzilla.cpp:359 +#: ../lib/Plugins/Bugzilla.cpp:442 msgid "Checking for duplicates..." msgstr "Controleren voor dubbele..." -#: ../lib/Plugins/Bugzilla.cpp:362 +#: ../lib/Plugins/Bugzilla.cpp:445 msgid "Logging into bugzilla..." msgstr "Inloggen bij bugzilla..." -#: ../lib/Plugins/Bugzilla.cpp:366 +#: ../lib/Plugins/Bugzilla.cpp:449 msgid "Empty login and password. Please check Bugzilla.conf" msgstr "Leeg login en wachtwoord. Check a.u.b. Bugzilla.conf" -#: ../lib/Plugins/Bugzilla.cpp:372 +#: ../lib/Plugins/Bugzilla.cpp:455 msgid "Checking CC..." msgstr "Controleren van CC..." -#: ../lib/Plugins/Bugzilla.cpp:381 +#: ../lib/Plugins/Bugzilla.cpp:464 msgid "Creating new bug..." msgstr "Nieuwe bug aanmaken..." -#: ../lib/Plugins/Bugzilla.cpp:385 +#: ../lib/Plugins/Bugzilla.cpp:468 msgid "Logging out..." msgstr "Uitloggen..." @@ -496,23 +500,23 @@ msgstr "Uitloggen..." msgid "Getting local universal unique identification" msgstr "Verkrijgen van locale universele unieke identificatie" -#: ../lib/Plugins/CCpp.cpp:254 +#: ../lib/Plugins/CCpp.cpp:257 msgid "Generating backtrace" msgstr "Aangemaakte backtrace" -#: ../lib/Plugins/CCpp.cpp:372 +#: ../lib/Plugins/CCpp.cpp:376 msgid "Starting debuginfo installation" msgstr "Start debuginfo installatie" -#: ../lib/Plugins/CCpp.cpp:522 +#: ../lib/Plugins/CCpp.cpp:527 msgid "Getting local universal unique identification..." msgstr "Verkrijgen van locale universele unieke identificatie..." -#: ../lib/Plugins/CCpp.cpp:541 +#: ../lib/Plugins/CCpp.cpp:546 msgid "Getting global universal unique identification..." msgstr "Verkrijgen van golbale universele unieke identificatie..." -#: ../lib/Plugins/CCpp.cpp:683 +#: ../lib/Plugins/CCpp.cpp:725 msgid "Skipping debuginfo installation" msgstr "Sla debuginfo installatie over" @@ -525,7 +529,7 @@ msgstr "Aanmaken en indienen van rapport..." msgid "Writing report to '%s'" msgstr "Rapport schrijven naar: '%s'" -#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:385 +#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:372 msgid "FileTransfer: URL not specified" msgstr "Bestandsoverdracht: URL niet opgegeven" @@ -534,16 +538,16 @@ msgstr "Bestandsoverdracht: URL niet opgegeven" msgid "Sending archive %s to %s" msgstr "Versturen van archief %s naar %s" -#: ../lib/Plugins/FileTransfer.cpp:310 +#: ../lib/Plugins/FileTransfer.cpp:296 msgid "File Transfer: Creating a report..." msgstr "Bestandsoverdracht: Een rapport maken..." -#: ../lib/Plugins/FileTransfer.cpp:335 +#: ../lib/Plugins/FileTransfer.cpp:322 #, c-format msgid "Can't create and send an archive: %s" msgstr "Kan geen archief maken en versturen: %s" -#: ../lib/Plugins/FileTransfer.cpp:360 +#: ../lib/Plugins/FileTransfer.cpp:347 #, c-format msgid "Can't create and send an archive %s" msgstr "Kan archief %s niet aanmaken en versturen" @@ -552,7 +556,7 @@ msgstr "Kan archief %s niet aanmaken en versturen" msgid "Creating kernel oops crash reports..." msgstr "Aanmaken van kernel oops crash rapporten..." -#: ../lib/Plugins/Mailx.cpp:164 +#: ../lib/Plugins/Mailx.cpp:147 msgid "Sending an email..." msgstr "Versturen van email..." @@ -565,7 +569,7 @@ msgstr "Uitvoeren van SOSreport plugin..." msgid "running sosreport: %s" msgstr "sosreport draaien: %s" -#: ../lib/Plugins/SOSreport.cpp:95 +#: ../lib/Plugins/SOSreport.cpp:97 msgid "done running sosreport" msgstr "klaar met het draaien van sosreport" -- cgit From d3eb4278cc246e23b24c9a99eb0867ff6cbe0c0b Mon Sep 17 00:00:00 2001 From: raven Date: Thu, 14 Jan 2010 21:54:42 +0000 Subject: Sending translation for Polish --- po/pl.po | 90 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/po/pl.po b/po/pl.po index 686692a..ec40469 100644 --- a/po/pl.po +++ b/po/pl.po @@ -7,10 +7,10 @@ msgid "" msgstr "" "Project-Id-Version: pl\n" "Report-Msgid-Bugs-To: jmoskovc@redhat.com\n" -"POT-Creation-Date: 2009-12-19 09:12+0000\n" -"PO-Revision-Date: 2009-12-19 10:37+0100\n" +"POT-Creation-Date: 2010-01-14 20:43+0000\n" +"PO-Revision-Date: 2010-01-14 22:51+0100\n" "Last-Translator: Piotr Drąg \n" -"Language-Team: Polish \n" +"Language-Team: Polish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -25,26 +25,26 @@ msgstr "" "Otrzymano nieoczekiwane dane od demona (czy baza danych została właściwie " "zaktualizowana?)." -#: ../src/Gui/ABRTPlugin.py:55 +#: ../src/Gui/ABRTPlugin.py:56 +msgid "Not loaded plugins" +msgstr "Nie wczytano wtyczek" + +#: ../src/Gui/ABRTPlugin.py:57 msgid "Analyzer plugins" msgstr "Wtyczki analizy" -#: ../src/Gui/ABRTPlugin.py:56 +#: ../src/Gui/ABRTPlugin.py:58 msgid "Action plugins" msgstr "Wtyczki działań" -#: ../src/Gui/ABRTPlugin.py:57 +#: ../src/Gui/ABRTPlugin.py:59 msgid "Reporter plugins" msgstr "Wtyczki zgłaszania" -#: ../src/Gui/ABRTPlugin.py:58 +#: ../src/Gui/ABRTPlugin.py:60 msgid "Database plugins" msgstr "Wtyczki baz danych" -#: ../src/Gui/ABRTPlugin.py:97 -msgid "Plugin name is not set, can't load its settings" -msgstr "Nie ustawiono nazwy wtyczki, nie można wczytać jej ustawień" - #: ../src/Gui/CCDBusBackend.py:74 ../src/Gui/CCDBusBackend.py:97 msgid "Can't connect to system dbus" msgstr "Nie można połączyć się z systemową magistralą D-Bus" @@ -140,31 +140,31 @@ msgid "_Help" msgstr "Pomo_c" #. add pixbuff separatelly -#: ../src/Gui/CCMainWindow.py:71 +#: ../src/Gui/CCMainWindow.py:77 msgid "Icon" msgstr "Ikona" -#: ../src/Gui/CCMainWindow.py:79 +#: ../src/Gui/CCMainWindow.py:85 msgid "Package" msgstr "Pakiet" -#: ../src/Gui/CCMainWindow.py:80 +#: ../src/Gui/CCMainWindow.py:86 msgid "Application" msgstr "Aplikacja" -#: ../src/Gui/CCMainWindow.py:81 +#: ../src/Gui/CCMainWindow.py:87 msgid "Date" msgstr "Data" -#: ../src/Gui/CCMainWindow.py:82 +#: ../src/Gui/CCMainWindow.py:88 msgid "Crash count" msgstr "Liczba awarii" -#: ../src/Gui/CCMainWindow.py:83 +#: ../src/Gui/CCMainWindow.py:89 msgid "User" msgstr "Użytkownik" -#: ../src/Gui/CCMainWindow.py:149 +#: ../src/Gui/CCMainWindow.py:157 #, python-format msgid "" "Can't show the settings dialog\n" @@ -173,7 +173,7 @@ msgstr "" "Nie można wyświetlić okna dialogowego ustawień\n" "%s" -#: ../src/Gui/CCMainWindow.py:160 +#: ../src/Gui/CCMainWindow.py:168 #, python-format msgid "" "Unable to finish current task!\n" @@ -183,7 +183,7 @@ msgstr "" "%s" #. there is something wrong with the daemon if we cant get the dumplist -#: ../src/Gui/CCMainWindow.py:187 +#: ../src/Gui/CCMainWindow.py:195 #, python-format msgid "" "Error while loading the dumplist.\n" @@ -192,15 +192,15 @@ msgstr "" "Błąd podczas wczytywania listy zrzutów.\n" "%s" -#: ../src/Gui/CCMainWindow.py:224 +#: ../src/Gui/CCMainWindow.py:232 msgid "This crash has been reported:\n" msgstr "Ta awaria została zgłoszona:\n" -#: ../src/Gui/CCMainWindow.py:234 +#: ../src/Gui/CCMainWindow.py:242 msgid "Not reported!" msgstr "Nie zgłoszono." -#: ../src/Gui/CCMainWindow.py:283 +#: ../src/Gui/CCMainWindow.py:291 msgid "" "Unable to get report!\n" "Debuginfo is missing?" @@ -208,7 +208,7 @@ msgstr "" "Nie można uzyskać raportu.\n" "Brak pakietów debuginfo?" -#: ../src/Gui/CCMainWindow.py:302 +#: ../src/Gui/CCMainWindow.py:310 #, python-format msgid "" "Reporting failed!\n" @@ -217,7 +217,7 @@ msgstr "" "Zgłoszenie nie powiodło się.\n" "%s" -#: ../src/Gui/CCMainWindow.py:321 ../src/Gui/CCMainWindow.py:348 +#: ../src/Gui/CCMainWindow.py:329 ../src/Gui/CCMainWindow.py:356 #, python-format msgid "Error getting the report: %s" msgstr "Błąd podczas uzyskiwania raportu: %s" @@ -447,11 +447,11 @@ msgstr "Wykryto awarię pakietu %s" msgid "ABRT service is not running" msgstr "Usługa ABRT nie jest uruchomiona" -#: ../src/Applet/CCApplet.cpp:196 +#: ../src/Applet/CCApplet.cpp:200 msgid "Warning" msgstr "Ostrzeżenie" -#: ../src/Daemon/Daemon.cpp:478 +#: ../src/Daemon/Daemon.cpp:474 msgid "" "Report size exceeded the quota. Please check system's MaxCrashReportsSize " "value in abrt.conf." @@ -459,37 +459,37 @@ msgstr "" "Wielkość raportu przekroczyła dozwolone ograniczenie. Proszę sprawdzić " "wartość zmiennej MaxCrashReportsSize w pliku abrt.conf" -#: ../lib/Plugins/Bugzilla.cpp:202 +#: ../lib/Plugins/Bugzilla.cpp:265 #, c-format msgid "Bug is already reported: %i" msgstr "Błąd został już wcześniej zgłoszony: %i" -#: ../lib/Plugins/Bugzilla.cpp:264 +#: ../lib/Plugins/Bugzilla.cpp:341 #, c-format msgid "New bug id: %i" msgstr "Identyfikator nowego błędu: %i" -#: ../lib/Plugins/Bugzilla.cpp:359 +#: ../lib/Plugins/Bugzilla.cpp:442 msgid "Checking for duplicates..." msgstr "Sprawdzanie duplikatów..." -#: ../lib/Plugins/Bugzilla.cpp:362 +#: ../lib/Plugins/Bugzilla.cpp:445 msgid "Logging into bugzilla..." msgstr "Logowanie do Bugzilli..." -#: ../lib/Plugins/Bugzilla.cpp:366 +#: ../lib/Plugins/Bugzilla.cpp:449 msgid "Empty login and password. Please check Bugzilla.conf" msgstr "Pola login i hasło są puste. Proszę sprawdzić plik Bugzilla.conf" -#: ../lib/Plugins/Bugzilla.cpp:372 +#: ../lib/Plugins/Bugzilla.cpp:455 msgid "Checking CC..." msgstr "Sprawdzanie listy CC..." -#: ../lib/Plugins/Bugzilla.cpp:381 +#: ../lib/Plugins/Bugzilla.cpp:464 msgid "Creating new bug..." msgstr "Dodawanie nowego błędu..." -#: ../lib/Plugins/Bugzilla.cpp:385 +#: ../lib/Plugins/Bugzilla.cpp:468 msgid "Logging out..." msgstr "Wylogowywanie..." @@ -501,19 +501,19 @@ msgstr "Uzyskiwanie lokalnego uniwersalnego, unikalnego identyfikatora" msgid "Generating backtrace" msgstr "Tworzenie wyjątku" -#: ../lib/Plugins/CCpp.cpp:375 +#: ../lib/Plugins/CCpp.cpp:376 msgid "Starting debuginfo installation" msgstr "Uruchamianie instalacji pakietów debuginfo" -#: ../lib/Plugins/CCpp.cpp:525 +#: ../lib/Plugins/CCpp.cpp:527 msgid "Getting local universal unique identification..." msgstr "Uzyskiwanie lokalnego uniwersalnego, unikalnego identyfikatora..." -#: ../lib/Plugins/CCpp.cpp:544 +#: ../lib/Plugins/CCpp.cpp:546 msgid "Getting global universal unique identification..." msgstr "Uzyskiwanie globalnego uniwersalnego, unikalnego identyfikatora..." -#: ../lib/Plugins/CCpp.cpp:687 +#: ../lib/Plugins/CCpp.cpp:725 msgid "Skipping debuginfo installation" msgstr "Pomijanie instalacji pakietu debuginfo" @@ -526,7 +526,7 @@ msgstr "Tworzenie i wysyłanie raportu..." msgid "Writing report to '%s'" msgstr "Zapisywanie raportu do \"%s\"" -#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:381 +#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:372 msgid "FileTransfer: URL not specified" msgstr "Wtyczka przesyłania plików: nie podano adresu URL" @@ -535,16 +535,16 @@ msgstr "Wtyczka przesyłania plików: nie podano adresu URL" msgid "Sending archive %s to %s" msgstr "Wysyłanie archiwum %s do %s" -#: ../lib/Plugins/FileTransfer.cpp:306 +#: ../lib/Plugins/FileTransfer.cpp:296 msgid "File Transfer: Creating a report..." msgstr "Wtyczka przesyłania plików: tworzenie raportu..." -#: ../lib/Plugins/FileTransfer.cpp:331 +#: ../lib/Plugins/FileTransfer.cpp:322 #, c-format msgid "Can't create and send an archive: %s" msgstr "Nie można utworzyć i wysłać archiwum: %s" -#: ../lib/Plugins/FileTransfer.cpp:356 +#: ../lib/Plugins/FileTransfer.cpp:347 #, c-format msgid "Can't create and send an archive %s" msgstr "Nie można utworzyć i wysłać archiwum %s" @@ -553,7 +553,7 @@ msgstr "Nie można utworzyć i wysłać archiwum %s" msgid "Creating kernel oops crash reports..." msgstr "Tworzenie raportów awarii \"kernel oops\"" -#: ../lib/Plugins/Mailx.cpp:164 +#: ../lib/Plugins/Mailx.cpp:147 msgid "Sending an email..." msgstr "Wysłanie wiadomości e-mail..." @@ -566,6 +566,6 @@ msgstr "Wykonywanie wtyczki SOSreport..." msgid "running sosreport: %s" msgstr "wykonywanie sosreport: %s" -#: ../lib/Plugins/SOSreport.cpp:95 +#: ../lib/Plugins/SOSreport.cpp:97 msgid "done running sosreport" msgstr "ukończono wykonywanie sosreport" -- cgit From 1ff447ffaaa02cd0c46607f817c13328114145bc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 14 Jan 2010 23:06:00 +0100 Subject: add code to make GUI -> daemon settings passing less weird. not enabled yet Signed-off-by: Denys Vlasenko --- src/Gui/CCDBusBackend.py | 2 +- src/Gui/CCMainWindow.py | 8 +++- src/Gui/ConfBackend.py | 100 +++++++++++++++++++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py index 1ec2d8a..f4ef104 100644 --- a/src/Gui/CCDBusBackend.py +++ b/src/Gui/CCDBusBackend.py @@ -40,7 +40,7 @@ class DBusManager(gobject.GObject): if session: try: - app_proxy = session.get_object(APP_NAME,APP_PATH) + app_proxy = session.get_object(APP_NAME, APP_PATH) app_iface = dbus.Interface(app_proxy, dbus_interface=APP_IFACE) # app is running, so make it show it self app_iface.show() diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py index 432fd43..0bc00e5 100644 --- a/src/Gui/CCMainWindow.py +++ b/src/Gui/CCMainWindow.py @@ -18,6 +18,7 @@ try: except Exception, ex: rpm = None +from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError import CCDBusBackend from CC_gui_functions import * from CCDumpList import getDumpList, DumpList @@ -42,11 +43,10 @@ class MainWindow(): sys.exit() except Exception, e: # show error message if connection fails - # FIXME add an option to start the daemon gui_error_message("%s" % e) sys.exit() #Set the Glade file - self.gladefile = "%s%sccgui.glade" % (sys.path[0],"/") + self.gladefile = "%s/ccgui.glade" % sys.path[0] self.wTree = gtk.glade.XML(self.gladefile) #Get the Main Window, and connect the "destroy" event @@ -304,6 +304,10 @@ class MainWindow(): self.pluginlist = getPluginInfoList(self.ccdaemon) for plugin in self.pluginlist.getReporterPlugins(): reporters_settings[str(plugin)] = plugin.Settings + # TODO: this way, we don't need to talk to daemon in order to get + # all plugin settings: + #reporters_settings2 = ConfBackendGnomeKeyring().load_all() + #log1("reporters_settings2:%s", str(reporters_settings2)) self.ccdaemon.Report(result, reporters_settings) #self.hydrate() except Exception, e: diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py index 08ceed5..fa1d663 100644 --- a/src/Gui/ConfBackend.py +++ b/src/Gui/ConfBackend.py @@ -2,6 +2,7 @@ from abrt_utils import _, log, log1, log2 # Doc on Gnome keyring API: # http://library.gnome.org/devel/gnome-keyring/stable/ +# Python bindings are in gnome-python2-desktop package #FIXME: add some backend factory @@ -56,14 +57,19 @@ class ConfBackend(object): # The attribute "AbrtPluginInfo" is special, it is used for retrieving # the key via keyring API find_items_sync() function. +g_default_key_ring = None class ConfBackendGnomeKeyring(ConfBackend): def __init__(self): + global g_default_key_ring + ConfBackend.__init__(self) + if g_default_key_ring: + return if not gkey.is_available(): raise ConfBackendInitError(_("Can't connect to Gnome Keyring daemon")) try: - self.default_key_ring = gkey.get_default_keyring_sync() + g_default_key_ring = gkey.get_default_keyring_sync() except: # could happen if keyring daemon is running, but we run gui under # user who is not the owner of the running session - using su @@ -71,31 +77,36 @@ class ConfBackendGnomeKeyring(ConfBackend): def save(self, name, settings): settings_tmp = settings.copy() - settings_tmp["AbrtPluginInfo"] = name - password = "" + settings_tmp["AbrtPluginInfo"] = name # old way + settings_tmp["Application"] = "abrt" + settings_tmp["AbrtPluginName"] = name - item_list = [] + # delete all keyring items containg "AbrtPluginInfo":"", + # so we always have only 1 item per plugin try: - item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)}) + item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, { "AbrtPluginInfo": str(name) }) + for item in item_list: + log2("found old keyring item: ring:'%s' item_id:%s attrs:%s", item.keyring, item.item_id, str(item.attributes)) + log2("deleting it from keyring '%s'", g_default_key_ring) + gkey.item_delete_sync(g_default_key_ring, item.item_id) except gkey.NoMatchError: # nothing found pass except gkey.DeniedError: raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved.")) - - # delete all items containg "AbrtPluginInfo":, so we always have only 1 item per plugin - for item in item_list: - gkey.item_delete_sync(self.default_key_ring, item.item_id) - + # if plugin has a "Password" setting, we handle it specially: in keyring, + # it is stored as item.secret, not as one of attributes + password = "" if "Password" in settings_tmp: password = settings_tmp["Password"] del settings_tmp["Password"] + # store new settings for this plugin as one keyring item try: - gkey.item_create_sync(self.default_key_ring, + gkey.item_create_sync(g_default_key_ring, gkey.ITEM_GENERIC_SECRET, - "abrt:%s" % name, - settings_tmp, - password, + "abrt:%s" % name, # display_name + settings_tmp, # attrs + password, # secret True) except gkey.DeniedError, e: raise ConfBackendSaveError(_("Access to gnome-keyring has been denied, plugins settings won't be saved.")) @@ -103,17 +114,66 @@ class ConfBackendGnomeKeyring(ConfBackend): def load(self, name): item_list = None try: + log2("looking for keyring items with 'AbrtPluginInfo:%s' attr", str(name)) item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, {"AbrtPluginInfo":str(name)}) + for item in item_list: + # gnome keyring is weeeeird. why display_name, type, mtime, ctime + # aren't available in find_items_sync() results? why we need to + # get them via additional call, item_get_info_sync()? + # internally, item has GNOME_KEYRING_TYPE_FOUND type, + # and info has GNOME_KEYRING_TYPE_ITEM_INFO type. + # why not use the same type for both? + # + # and worst of all, this information took four hours of googling... + # + #info = gkey.item_get_info_sync(item.keyring, item.item_id) + log2("found keyring item: ring:'%s' item_id:%s attrs:%s", # "secret:'%s' display_name:'%s'" + item.keyring, item.item_id, str(item.attributes) #, item.secret, info.get_display_name() + ) except gkey.NoMatchError: # nothing found pass - if item_list: retval = item_list[0].attributes.copy() retval["Password"] = item_list[0].secret return retval - else: - return {} - #for i in item_list: - # for attr in i.attributes: - # print attr, i.attributes[attr] + return {} + + # This routine loads setting for all plugins. It doesn't need plugin name. + # Thus we can avoid talking to abrtd just in order to get plugin names. + def load_all(self): + retval = {} + item_list = {} + try: + log2("looking for keyring items with 'Application:abrt' attr") + item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, { "Application": "abrt" }) + except gkey.NoMatchError: + # nothing found + pass + for item in item_list: + # gnome keyring is weeeeird. why display_name, type, mtime, ctime + # aren't available in find_items_sync() results? why we need to + # get them via additional call, item_get_info_sync()? + # internally, item has GNOME_KEYRING_TYPE_FOUND type, + # and info has GNOME_KEYRING_TYPE_ITEM_INFO type. + # why not use the same type for both? + # + # and worst of all, this information took four hours of googling... + # + #info = gkey.item_get_info_sync(item.keyring, item.item_id) + log2("found keyring item: ring:%s item_id:%s attrs:%s", # "secret:%s display_name:'%s'" + item.keyring, item.item_id, str(item.attributes) #, item.secret, info.get_display_name() + ) + attrs = item.attributes.copy() + if "AbrtPluginName" in attrs: + plugin_name = attrs["AbrtPluginName"] + # If plugin has a "Password" setting, we handle it specially: in keyring, + # it is stored as item.secret, not as one of attributes + if item.secret: + attrs["Password"] = item.secret + # avoiding sending useless duplicate info over dbus... + del attrs["Application"] + del attrs["AbrtPluginInfo"] + del attrs["AbrtPluginName"] + retval[plugin_name] = attrs; + return retval -- cgit From 076b7664099cf06dd3d34de5d48665b502b299f2 Mon Sep 17 00:00:00 2001 From: elsupergomez Date: Fri, 15 Jan 2010 13:11:45 +0000 Subject: Sending translation for Spanish --- po/es.po | 97 +++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/po/es.po b/po/es.po index c732c21..2e5b5f6 100644 --- a/po/es.po +++ b/po/es.po @@ -9,9 +9,9 @@ msgid "" msgstr "" "Project-Id-Version: abrt.master.es\n" "Report-Msgid-Bugs-To: jmoskovc@redhat.com\n" -"POT-Creation-Date: 2009-12-15 10:52+0000\n" -"PO-Revision-Date: 2009-12-15 11:51-0300\n" -"Last-Translator: Héctor Daniel Cabrera \n" +"POT-Creation-Date: 2010-01-15 11:23+0000\n" +"PO-Revision-Date: 2010-01-15 10:06-0300\n" +"Last-Translator: Claudio Rodrigo Pereyra Diaz \n" "Language-Team: Fedora Spanish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -28,26 +28,26 @@ msgstr "Otro cliente ya está siendo ejecutado, intentando despertarlo." msgid "Got unexpected data from daemon (is the database properly updated?)." msgstr "Se obtienen datos inesperados desde el demonio (¿está la Base de Datos correctamente actualizada?)" -#: ../src/Gui/ABRTPlugin.py:55 +#: ../src/Gui/ABRTPlugin.py:56 +msgid "Not loaded plugins" +msgstr "Complementos no cargados" + +#: ../src/Gui/ABRTPlugin.py:57 msgid "Analyzer plugins" msgstr "Complementos analizadores" -#: ../src/Gui/ABRTPlugin.py:56 +#: ../src/Gui/ABRTPlugin.py:58 msgid "Action plugins" msgstr "Complementos de acción" -#: ../src/Gui/ABRTPlugin.py:57 +#: ../src/Gui/ABRTPlugin.py:59 msgid "Reporter plugins" msgstr "Complementos de informes" -#: ../src/Gui/ABRTPlugin.py:58 +#: ../src/Gui/ABRTPlugin.py:60 msgid "Database plugins" msgstr "Complementos de Bases de Datos" -#: ../src/Gui/ABRTPlugin.py:97 -msgid "Plugin name is not set, can't load its settings" -msgstr "No se puso el nombre del complemento, no se puede cargar su configuración" - #: ../src/Gui/CCDBusBackend.py:74 #: ../src/Gui/CCDBusBackend.py:97 msgid "Can't connect to system dbus" @@ -134,31 +134,31 @@ msgstr "Ay_uda" # Revisar si hay que traducir. # Ver como referencia los botones gtk que no habia que traducirlos #. add pixbuff separatelly -#: ../src/Gui/CCMainWindow.py:71 +#: ../src/Gui/CCMainWindow.py:77 msgid "Icon" msgstr "Icono" -#: ../src/Gui/CCMainWindow.py:79 +#: ../src/Gui/CCMainWindow.py:85 msgid "Package" msgstr "Paquete" -#: ../src/Gui/CCMainWindow.py:80 +#: ../src/Gui/CCMainWindow.py:86 msgid "Application" msgstr "Aplicación" -#: ../src/Gui/CCMainWindow.py:81 +#: ../src/Gui/CCMainWindow.py:87 msgid "Date" msgstr "Fecha" -#: ../src/Gui/CCMainWindow.py:82 +#: ../src/Gui/CCMainWindow.py:88 msgid "Crash count" msgstr "Cantidad de caídas" -#: ../src/Gui/CCMainWindow.py:83 +#: ../src/Gui/CCMainWindow.py:89 msgid "User" msgstr "Usuario" -#: ../src/Gui/CCMainWindow.py:149 +#: ../src/Gui/CCMainWindow.py:157 #, python-format msgid "" "Can't show the settings dialog\n" @@ -167,7 +167,7 @@ msgstr "" "No se puede mostrar el diálogo de configuración\n" "%s" -#: ../src/Gui/CCMainWindow.py:160 +#: ../src/Gui/CCMainWindow.py:168 #, python-format msgid "" "Unable to finish current task!\n" @@ -177,7 +177,7 @@ msgstr "" "%s" #. there is something wrong with the daemon if we cant get the dumplist -#: ../src/Gui/CCMainWindow.py:184 +#: ../src/Gui/CCMainWindow.py:195 #, python-format msgid "" "Error while loading the dumplist.\n" @@ -186,15 +186,15 @@ msgstr "" "Error intentando cargar la lista de volcado.\n" "%s" -#: ../src/Gui/CCMainWindow.py:221 +#: ../src/Gui/CCMainWindow.py:232 msgid "This crash has been reported:\n" msgstr " Esta caída ha sido reportada:\n" -#: ../src/Gui/CCMainWindow.py:231 +#: ../src/Gui/CCMainWindow.py:242 msgid "Not reported!" msgstr "¡No informado!" -#: ../src/Gui/CCMainWindow.py:280 +#: ../src/Gui/CCMainWindow.py:291 msgid "" "Unable to get report!\n" "Debuginfo is missing?" @@ -202,7 +202,7 @@ msgstr "" "Incapaz de conseguir el informe!\n" "¿Falta la información de la depuración?" -#: ../src/Gui/CCMainWindow.py:299 +#: ../src/Gui/CCMainWindow.py:314 #, python-format msgid "" "Reporting failed!\n" @@ -211,8 +211,8 @@ msgstr "" "¡El informe falló!\n" "%s" -#: ../src/Gui/CCMainWindow.py:318 -#: ../src/Gui/CCMainWindow.py:345 +#: ../src/Gui/CCMainWindow.py:333 +#: ../src/Gui/CCMainWindow.py:360 #, python-format msgid "Error getting the report: %s" msgstr "Error al obtener el informe: %s" @@ -435,45 +435,45 @@ msgstr "Ha sido detectado una caída en el paquete %s." msgid "ABRT service is not running" msgstr "El servicio ABRT no se está ejecutando" -#: ../src/Applet/CCApplet.cpp:196 +#: ../src/Applet/CCApplet.cpp:200 msgid "Warning" msgstr "Aviso" -#: ../src/Daemon/Daemon.cpp:473 +#: ../src/Daemon/Daemon.cpp:474 msgid "Report size exceeded the quota. Please check system's MaxCrashReportsSize value in abrt.conf." msgstr "El tamaño del informe excede la cuota. Por favor, verifique el valor de MaxCrashReportsSize del sistema en abrt.conf." -#: ../lib/Plugins/Bugzilla.cpp:202 +#: ../lib/Plugins/Bugzilla.cpp:265 #, c-format msgid "Bug is already reported: %i" msgstr "El error ya ha sido informado: %i" -#: ../lib/Plugins/Bugzilla.cpp:264 +#: ../lib/Plugins/Bugzilla.cpp:341 #, c-format msgid "New bug id: %i" msgstr "Nuevo id del error: %i" -#: ../lib/Plugins/Bugzilla.cpp:359 +#: ../lib/Plugins/Bugzilla.cpp:442 msgid "Checking for duplicates..." msgstr "Chequeando si hay duplicados..." -#: ../lib/Plugins/Bugzilla.cpp:362 +#: ../lib/Plugins/Bugzilla.cpp:445 msgid "Logging into bugzilla..." msgstr "Ingresando a bugzilla..." -#: ../lib/Plugins/Bugzilla.cpp:366 +#: ../lib/Plugins/Bugzilla.cpp:449 msgid "Empty login and password. Please check Bugzilla.conf" msgstr "Usuario y contraseña vacios. Por favor compruebe el archivo Bugzilla.conf" -#: ../lib/Plugins/Bugzilla.cpp:372 +#: ../lib/Plugins/Bugzilla.cpp:455 msgid "Checking CC..." msgstr "Chequeando CC..." -#: ../lib/Plugins/Bugzilla.cpp:381 +#: ../lib/Plugins/Bugzilla.cpp:464 msgid "Creating new bug..." msgstr "Creando un nuevo informe..." -#: ../lib/Plugins/Bugzilla.cpp:385 +#: ../lib/Plugins/Bugzilla.cpp:468 msgid "Logging out..." msgstr "Saliendo..." @@ -481,23 +481,23 @@ msgstr "Saliendo..." msgid "Getting local universal unique identification" msgstr "Obteniendo la identificación única universal local" -#: ../lib/Plugins/CCpp.cpp:254 +#: ../lib/Plugins/CCpp.cpp:257 msgid "Generating backtrace" msgstr "Generando seguimiento..." -#: ../lib/Plugins/CCpp.cpp:372 +#: ../lib/Plugins/CCpp.cpp:376 msgid "Starting debuginfo installation" msgstr "Iniciando la instalación de la información de depuración" -#: ../lib/Plugins/CCpp.cpp:524 +#: ../lib/Plugins/CCpp.cpp:527 msgid "Getting local universal unique identification..." msgstr "Obteniendo la identificación única universal local..." -#: ../lib/Plugins/CCpp.cpp:543 +#: ../lib/Plugins/CCpp.cpp:546 msgid "Getting global universal unique identification..." msgstr "Obteniendo la identificación única universal global..." -#: ../lib/Plugins/CCpp.cpp:685 +#: ../lib/Plugins/CCpp.cpp:725 msgid "Skipping debuginfo installation" msgstr "Omita la instalación de la información de depuración" @@ -511,7 +511,7 @@ msgid "Writing report to '%s'" msgstr "Escribiendo reporte en '%s'" #: ../lib/Plugins/FileTransfer.cpp:63 -#: ../lib/Plugins/FileTransfer.cpp:385 +#: ../lib/Plugins/FileTransfer.cpp:372 msgid "FileTransfer: URL not specified" msgstr "Transferencia de archivo: URL no especificada" @@ -520,16 +520,16 @@ msgstr "Transferencia de archivo: URL no especificada" msgid "Sending archive %s to %s" msgstr "Enviando archivo %s a %s" -#: ../lib/Plugins/FileTransfer.cpp:310 +#: ../lib/Plugins/FileTransfer.cpp:296 msgid "File Transfer: Creating a report..." msgstr "Transferencia de archivo: Creando un informe..." -#: ../lib/Plugins/FileTransfer.cpp:335 +#: ../lib/Plugins/FileTransfer.cpp:322 #, c-format msgid "Can't create and send an archive: %s" msgstr "No se puede crear y enviar un archivo: %s" -#: ../lib/Plugins/FileTransfer.cpp:360 +#: ../lib/Plugins/FileTransfer.cpp:347 #, c-format msgid "Can't create and send an archive %s" msgstr "No se puede crear y enviar un archivo %s" @@ -538,7 +538,7 @@ msgstr "No se puede crear y enviar un archivo %s" msgid "Creating kernel oops crash reports..." msgstr "Creando un informe de cuelgue de kernel oops..." -#: ../lib/Plugins/Mailx.cpp:164 +#: ../lib/Plugins/Mailx.cpp:147 msgid "Sending an email..." msgstr "Enviando un correo..." @@ -551,10 +551,13 @@ msgstr "Ejecutando complemento SOSreport..." msgid "running sosreport: %s" msgstr "ejecutando sosreport: %s" -#: ../lib/Plugins/SOSreport.cpp:95 +#: ../lib/Plugins/SOSreport.cpp:97 msgid "done running sosreport" msgstr "Sosreport corriendo" +#~ msgid "Plugin name is not set, can't load its settings" +#~ msgstr "" +#~ "No se puso el nombre del complemento, no se puede cargar su configuración" #~ msgid "Searching for debug-info packages..." #~ msgstr "Buscando paquetes de información del depurador..." #~ msgid "Downloading and installing debug-info packages..." -- cgit From f0e636a2bac1d6a76fed613bee9505b4abfdf8b1 Mon Sep 17 00:00:00 2001 From: Jiri Moskovcak Date: Fri, 15 Jan 2010 15:18:22 +0100 Subject: use repr() to print variable values in python hook --- src/Hooks/abrt_exception_handler.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in index a0b0519..e0e1954 100644 --- a/src/Hooks/abrt_exception_handler.py.in +++ b/src/Hooks/abrt_exception_handler.py.in @@ -213,7 +213,7 @@ def handleMyException((etype, value, tb)): text += ("\nLocal variables in innermost frame:\n") try: for (key, val) in frame.f_locals.items(): - text += "%s: %s\n" % (key, val) + text += "%s: %s\n" % (key, repr(val)) except: pass -- cgit From 494ed25390a3c1fa831ca594b77135eb5f18fba8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Jan 2010 16:04:27 +0100 Subject: GUI: better code for plugin settings overriding; better logging; fixed "not reported" display bug Signed-off-by: Denys Vlasenko --- src/Gui/ABRTPlugin.py | 4 ++-- src/Gui/CCMainWindow.py | 31 ++++++++++++++---------- src/Gui/ConfBackend.py | 64 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/Gui/ABRTPlugin.py b/src/Gui/ABRTPlugin.py index 5fb551d..320c81c 100644 --- a/src/Gui/ABRTPlugin.py +++ b/src/Gui/ABRTPlugin.py @@ -11,14 +11,14 @@ Email Description """ from abrt_utils import _, log, log1, log2 -from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError +from ConfBackend import getCurrentConfBackend, ConfBackendInitError class PluginSettings(dict): def __init__(self): dict.__init__(self) self.client_side_conf = None try: - self.client_side_conf = ConfBackendGnomeKeyring() + self.client_side_conf = getCurrentConfBackend() except ConfBackendInitError, e: print e pass diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py index 0bc00e5..5ffc027 100644 --- a/src/Gui/CCMainWindow.py +++ b/src/Gui/CCMainWindow.py @@ -18,7 +18,7 @@ try: except Exception, ex: rpm = None -from ConfBackend import ConfBackendGnomeKeyring, ConfBackendInitError +from ConfBackend import getCurrentConfBackend, ConfBackendInitError import CCDBusBackend from CC_gui_functions import * from CCDumpList import getDumpList, DumpList @@ -234,9 +234,11 @@ class MainWindow(): # it is not informative (no URL to the report) for message in dump.getMessage().split('\n'): if message: - if "http" in message[0:5] or "file:///"[0:8] in message: - message = "%s" % (message, message) + #Doesn't work (far too easy to make it worse, not better): + #if "http" in message[0:5] or "file:///"[0:8] in message: + # message = "%s" % (message, message) report_label += "%s\n" % message + log2("setting markup '%s'", report_label) self.wTree.get_widget("lReported").set_markup(report_label) else: self.wTree.get_widget("lReported").set_markup(_("Not reported!")) @@ -298,17 +300,20 @@ class MainWindow(): try: self.pBarWindow.show_all() self.timer = gobject.timeout_add(100, self.progress_update_cb) - reporters_settings = {} - # self.pluginlist = getPluginInfoList(self.ccdaemon, refresh=True) - # don't force refresh! - self.pluginlist = getPluginInfoList(self.ccdaemon) - for plugin in self.pluginlist.getReporterPlugins(): - reporters_settings[str(plugin)] = plugin.Settings - # TODO: this way, we don't need to talk to daemon in order to get - # all plugin settings: - #reporters_settings2 = ConfBackendGnomeKeyring().load_all() - #log1("reporters_settings2:%s", str(reporters_settings2)) + # Old way: it needs to talk to daemon + #reporters_settings = {} + ## self.pluginlist = getPluginInfoList(self.ccdaemon, refresh=True) + ## don't force refresh! + #self.pluginlist = getPluginInfoList(self.ccdaemon) + #for plugin in self.pluginlist.getReporterPlugins(): + # reporters_settings[str(plugin)] = plugin.Settings + reporters_settings = getCurrentConfBackend().load_all() + log2("Report(result,settings):") + log2(" result:%s", str(result)) + # Careful, this will print reporters_settings["Password"] too + log2(" settings:%s", str(reporters_settings)) self.ccdaemon.Report(result, reporters_settings) + log2("Report() returned") #self.hydrate() except Exception, e: gui_error_message(_("Reporting failed!\n%s" % e)) diff --git a/src/Gui/ConfBackend.py b/src/Gui/ConfBackend.py index fa1d663..0d47760 100644 --- a/src/Gui/ConfBackend.py +++ b/src/Gui/ConfBackend.py @@ -4,8 +4,6 @@ from abrt_utils import _, log, log1, log2 # http://library.gnome.org/devel/gnome-keyring/stable/ # Python bindings are in gnome-python2-desktop package -#FIXME: add some backend factory - try: import gnomekeyring as gkey except ImportError, e: @@ -49,13 +47,14 @@ class ConfBackend(object): # # Example: Key "abrt:Bugzilla" with bugzilla password as value, and with attributes: # +# Application: abrt # AbrtPluginInfo: Bugzilla # NoSSLVerify: yes # Login: user@host.com # BugzillaURL: https://host.with.bz.com/ # -# The attribute "AbrtPluginInfo" is special, it is used for retrieving -# the key via keyring API find_items_sync() function. +# Attributes "Application" and "AbrtPluginInfo" are special, they are used +# for efficient key retrieval via keyring API find_items_sync() function. g_default_key_ring = None @@ -66,7 +65,7 @@ class ConfBackendGnomeKeyring(ConfBackend): ConfBackend.__init__(self) if g_default_key_ring: return - if not gkey.is_available(): + if not gkey or not gkey.is_available(): raise ConfBackendInitError(_("Can't connect to Gnome Keyring daemon")) try: g_default_key_ring = gkey.get_default_keyring_sync() @@ -77,9 +76,8 @@ class ConfBackendGnomeKeyring(ConfBackend): def save(self, name, settings): settings_tmp = settings.copy() - settings_tmp["AbrtPluginInfo"] = name # old way settings_tmp["Application"] = "abrt" - settings_tmp["AbrtPluginName"] = name + settings_tmp["AbrtPluginInfo"] = name # delete all keyring items containg "AbrtPluginInfo":"", # so we always have only 1 item per plugin @@ -144,6 +142,37 @@ class ConfBackendGnomeKeyring(ConfBackend): def load_all(self): retval = {} item_list = {} + + # UGLY compat cludge for users who has saved items without "Application" attr + # (abrt <= 1.0.3 was saving those) + item_ids = gkey.list_item_ids_sync(g_default_key_ring) + log2("all keyring item ids:%s", item_ids) + for item_id in item_ids: + info = gkey.item_get_info_sync(g_default_key_ring, item_id) + attrs = gkey.item_get_attributes_sync(g_default_key_ring, item_id) + log2("keyring item %s: attrs:%s", item_id, str(attrs)) + if "AbrtPluginInfo" in attrs: + if not "Application" in attrs: + log2("updating old-style keyring item") + attrs["Application"] = "abrt" + try: + gkey.item_set_attributes_sync(g_default_key_ring, item_id, attrs) + except: + log2("error updating old-style keyring item") + plugin_name = attrs["AbrtPluginInfo"] + # If plugin has a "Password" setting, we handle it specially: in keyring, + # it is stored as item.secret, not as one of attributes + if info.get_secret(): + attrs["Password"] = info.get_secret() + # avoiding sending useless duplicate info over dbus... + del attrs["AbrtPluginInfo"] + try: + del attrs["Application"] + except: + pass + retval[plugin_name] = attrs; + # end of UGLY compat cludge + try: log2("looking for keyring items with 'Application:abrt' attr") item_list = gkey.find_items_sync(gkey.ITEM_GENERIC_SECRET, { "Application": "abrt" }) @@ -165,15 +194,28 @@ class ConfBackendGnomeKeyring(ConfBackend): item.keyring, item.item_id, str(item.attributes) #, item.secret, info.get_display_name() ) attrs = item.attributes.copy() - if "AbrtPluginName" in attrs: - plugin_name = attrs["AbrtPluginName"] + if "AbrtPluginInfo" in attrs: + plugin_name = attrs["AbrtPluginInfo"] # If plugin has a "Password" setting, we handle it specially: in keyring, # it is stored as item.secret, not as one of attributes if item.secret: attrs["Password"] = item.secret # avoiding sending useless duplicate info over dbus... - del attrs["Application"] del attrs["AbrtPluginInfo"] - del attrs["AbrtPluginName"] + try: + del attrs["Application"] + except: + pass retval[plugin_name] = attrs; return retval + + +# Rudimentary backend factory + +currentConfBackend = None + +def getCurrentConfBackend(): + global currentConfBackend + if not currentConfBackend: + currentConfBackend = ConfBackendGnomeKeyring() + return currentConfBackend -- cgit From b41833ed61f7b579d2a46b26d261616c21a6ae32 Mon Sep 17 00:00:00 2001 From: ratal Date: Sun, 17 Jan 2010 15:11:08 +0000 Subject: Sending translation for French --- po/fr.po | 335 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 185 insertions(+), 150 deletions(-) diff --git a/po/fr.po b/po/fr.po index ceb709a..72b99e0 100644 --- a/po/fr.po +++ b/po/fr.po @@ -2,17 +2,18 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # -#: ../src/Gui/CCReporterDialog.py:196 +#: ../src/Gui/CCReporterDialog.py:208 # Sam Friedmann , 2009. # ratal , 2009. +# Aymeric Rateau , 2010. msgid "" msgstr "" "Project-Id-Version: abrt.master.fr\n" "Report-Msgid-Bugs-To: jmoskovc@redhat.com\n" -"POT-Creation-Date: 2009-11-23 08:40+0000\n" -"PO-Revision-Date: 2009-11-29 20:10+0900\n" -"Last-Translator: ratal \n" -"Language-Team: Français \n" +"POT-Creation-Date: 2010-01-08 15:37+0000\n" +"PO-Revision-Date: 2010-01-14 21:10+0100\n" +"Last-Translator: Aymeric Rateau \n" +"Language-Team: French \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -46,7 +47,7 @@ msgid "Database plugins" msgstr "Extensions de base de données" #: ../src/Gui/ABRTPlugin.py:97 -msgid "Plugin name is not set, can't load it's settings" +msgid "Plugin name is not set, can't load its settings" msgstr "" "Le nom de l'extension n'est pas défini, chargement de sa configuration " "impossible" @@ -55,59 +56,55 @@ msgstr "" msgid "Can't connect to system dbus" msgstr "Connexion au système dbus impossible" -#: ../src/Gui/CCDBusBackend.py:100 ../src/Gui/CCDBusBackend.py:103 +#: ../src/Gui/CCDBusBackend.py:104 ../src/Gui/CCDBusBackend.py:107 msgid "Please check if abrt daemon is running" msgstr "Veuillez vérifier que le démon abrt est en cours d'exécution." -#: ../src/Gui/CCDBusBackend.py:155 +#: ../src/Gui/CCDBusBackend.py:159 msgid "" -"Daemon did't return valid report info\n" +"Daemon didn't return valid report info\n" "Debuginfo is missing?" msgstr "" "Le démon n'a pas retourné d'informations valides\n" "Debuginfo est manquant ?" -#: ../src/Gui/ccgui.glade.h:1 ../src/Gui/report.glade.h:1 -msgid " " -msgstr " " - -#: ../src/Gui/ccgui.glade.h:2 +#: ../src/Gui/ccgui.glade.h:1 msgid "(C) 2009 Red Hat, Inc." msgstr "(C) 2009 Red Hat, Inc." -#: ../src/Gui/ccgui.glade.h:3 ../src/Gui/CCMainWindow.py:246 -msgid "Not reported!" -msgstr "Non signalé !" - -#: ../src/Gui/ccgui.glade.h:4 -msgid "Description" -msgstr "Description" - -#: ../src/Gui/ccgui.glade.h:5 +#: ../src/Gui/ccgui.glade.h:2 msgid "About ABRT" msgstr "À propos d'ABRT" -#: ../src/Gui/ccgui.glade.h:6 ../src/Gui/abrt.desktop.in.h:1 +#: ../src/Gui/ccgui.glade.h:3 ../src/Gui/abrt.desktop.in.h:1 msgid "Automatic Bug Reporting Tool" msgstr "Automatic Bug Reporting Tool" -#: ../src/Gui/ccgui.glade.h:7 +#: ../src/Gui/ccgui.glade.h:4 msgid "Delete" msgstr "Supprimer" -#: ../src/Gui/ccgui.glade.h:8 +#: ../src/Gui/ccgui.glade.h:5 +msgid "Details" +msgstr "Détails" + +#: ../src/Gui/ccgui.glade.h:6 +msgid "Not Reported" +msgstr "Non signalé" + +#: ../src/Gui/ccgui.glade.h:7 msgid "Please wait.." msgstr "Veuillez patienter..." -#: ../src/Gui/ccgui.glade.h:9 +#: ../src/Gui/ccgui.glade.h:8 msgid "Plugins" msgstr "Extensions" -#: ../src/Gui/ccgui.glade.h:10 ../src/Gui/report.glade.h:4 +#: ../src/Gui/ccgui.glade.h:9 ../src/Gui/report.glade.h:6 msgid "Report" msgstr "Rapport" -#: ../src/Gui/ccgui.glade.h:11 +#: ../src/Gui/ccgui.glade.h:10 msgid "" "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 " @@ -135,48 +132,44 @@ msgstr "" "Vous devriez avoir reçu une copie de la Licence Publique Générale GNU avec " "ce logiciel. Si ce n'est pas le cas, voir ." -#: ../src/Gui/ccgui.glade.h:16 -msgid "Working..." -msgstr "Traitement en cours..." - -#: ../src/Gui/ccgui.glade.h:17 +#: ../src/Gui/ccgui.glade.h:15 msgid "_Edit" msgstr "_Édition" -#: ../src/Gui/ccgui.glade.h:18 +#: ../src/Gui/ccgui.glade.h:16 msgid "_File" msgstr "_Fichier" -#: ../src/Gui/ccgui.glade.h:19 +#: ../src/Gui/ccgui.glade.h:17 msgid "_Help" msgstr "_Aide" #. add pixbuff separatelly -#: ../src/Gui/CCMainWindow.py:80 +#: ../src/Gui/CCMainWindow.py:76 msgid "Icon" msgstr "Icône" -#: ../src/Gui/CCMainWindow.py:88 +#: ../src/Gui/CCMainWindow.py:84 msgid "Package" msgstr "Paquet" -#: ../src/Gui/CCMainWindow.py:89 +#: ../src/Gui/CCMainWindow.py:85 msgid "Application" msgstr "Application" -#: ../src/Gui/CCMainWindow.py:90 +#: ../src/Gui/CCMainWindow.py:86 msgid "Date" msgstr "Date" -#: ../src/Gui/CCMainWindow.py:91 +#: ../src/Gui/CCMainWindow.py:87 msgid "Crash count" msgstr "Décompte d'incidents" -#: ../src/Gui/CCMainWindow.py:93 +#: ../src/Gui/CCMainWindow.py:88 msgid "User" msgstr "Utilisateur" -#: ../src/Gui/CCMainWindow.py:160 +#: ../src/Gui/CCMainWindow.py:156 #, python-format msgid "" "Can't show the settings dialog\n" @@ -185,7 +178,7 @@ msgstr "" "Affichage de l'interface de configuration impossible\n" "%s" -#: ../src/Gui/CCMainWindow.py:181 +#: ../src/Gui/CCMainWindow.py:167 #, python-format msgid "" "Unable to finish current task!\n" @@ -194,23 +187,25 @@ msgstr "" "Impossible de terminer la tâche actuelle !\n" "%s" -#: ../src/Gui/CCMainWindow.py:198 +#. there is something wrong with the daemon if we cant get the dumplist +#: ../src/Gui/CCMainWindow.py:194 #, python-format msgid "" -"Error while loading the dumplist, please check if abrt daemon is running\n" -" %s" +"Error while loading the dumplist.\n" +"%s" msgstr "" -"Erreur lors du chargement de dumplist, veuillez vérifier que le démon abrt " -"est bien en cours d'exécution\n" +"Erreur lors du chargement de dumplist.\n" " %s" -#: ../src/Gui/CCMainWindow.py:238 -msgid "This crash has been reported, you can find the report(s) at:\n" -msgstr "" -"Cet incident a été signalé, vous pourrez trouver ce(s) rapport(s) à :\n" +#: ../src/Gui/CCMainWindow.py:231 +msgid "This crash has been reported:\n" +msgstr "Cet incident a été signalé :\n" + +#: ../src/Gui/CCMainWindow.py:241 +msgid "Not reported!" +msgstr "Non signalé !" -#: ../src/Gui/CCMainWindow.py:298 +#: ../src/Gui/CCMainWindow.py:290 msgid "" "Unable to get report!\n" "Debuginfo is missing?" @@ -218,7 +213,7 @@ msgstr "" "Impossible de trouver le rapport !\n" "Debuginfo est manquant ?" -#: ../src/Gui/CCMainWindow.py:318 +#: ../src/Gui/CCMainWindow.py:309 #, python-format msgid "" "Reporting failed!\n" @@ -227,43 +222,52 @@ msgstr "" "Échec de la création de rapports !\n" "%s" -#: ../src/Gui/CCMainWindow.py:337 ../src/Gui/CCMainWindow.py:364 +#: ../src/Gui/CCMainWindow.py:328 ../src/Gui/CCMainWindow.py:355 #, python-format msgid "Error getting the report: %s" msgstr "Erreur lors de l'obtention du rapport : %s" -#: ../src/Gui/CCReporterDialog.py:182 +#: ../src/Gui/CCReporterDialog.py:136 +#, python-format +msgid "" +"Can't save plugin settings:\n" +" %s" +msgstr "" +"Imposible d'enregistrer la configuration de l'extension :\n" +" %s" + +#: ../src/Gui/CCReporterDialog.py:194 msgid "Brief description how to reproduce this or what you did..." msgstr "" "Brève description de la procédure à suivre pour reproduire ceci, ou de ce " "que vous avez fait..." -#: ../src/Gui/CCReporterDialog.py:224 +#: ../src/Gui/CCReporterDialog.py:239 #, python-format msgid "" "Reporting disabled because the backtrace is unusable.\n" -"Please try to install debuginfo manually using command: " -"debuginfo-install %s \n" +"Please try to install debuginfo manually using command: debuginfo-install " +"%s \n" "then use Refresh button to regenerate the backtrace." msgstr "" "Envoi du rapport désactivé car le backtrace est inutilisable.\n" -"Veuillez installer debuginfo en utilisant la commande : " -"debuginfo-install %s \n" +"Veuillez installer debuginfo en utilisant la commande :  " +"debuginfo-install %s \n" "puis utilisez le bouton de rafraichissement pour régénérer le backtrace." -#: ../src/Gui/CCReporterDialog.py:226 -msgid "The bactrace is unusable, you can't report this!" +#: ../src/Gui/CCReporterDialog.py:241 +msgid "The backtrace is unusable, you can't report this!" msgstr "Le backtrace est inutilisable, vous ne pouvez pas signaler ce bogue." -#: ../src/Gui/CCReporterDialog.py:232 +#: ../src/Gui/CCReporterDialog.py:246 msgid "" -"The bactrace is incomplete, please make sure you provide good steps to " +"The backtrace is incomplete, please make sure you provide good steps to " "reproduce." msgstr "" "Le backtrace est incomplet, veuillez vous assurer de fournir les étapes pour " "reproduire le bogue." -#: ../src/Gui/CCReporterDialog.py:280 +#: ../src/Gui/CCReporterDialog.py:296 #, python-format msgid "" "WARNING, you're about to send data which might contain sensitive " @@ -274,14 +278,14 @@ msgstr "" "des informations confidentielles.\n" "Voulez-vous vraiment envoyer %s ?\n" -#: ../src/Gui/dialogs.glade.h:1 +#: ../src/Gui/dialogs.glade.h:1 ../src/Gui/report.glade.h:5 +msgid "Log" +msgstr "Log" + +#: ../src/Gui/dialogs.glade.h:2 msgid "Report done" msgstr "Rapport créé" -#: ../src/Gui/dialogs.glade.h:2 ../src/Gui/settings.glade.h:27 -msgid "gtk-ok" -msgstr "gtk-ok" - #: ../src/Gui/PluginSettingsUI.py:18 msgid "Can't find PluginDialog widget in UI description!" msgstr "" @@ -302,15 +306,23 @@ msgstr "la boite combinée n'est pas implémentée" msgid "Nothing to hydrate!" msgstr "Aucune donnée à afficher !" +#: ../src/Gui/report.glade.h:1 +msgid " " +msgstr " " + #: ../src/Gui/report.glade.h:2 -msgid "Comment" -msgstr "Commenter" +msgid "Comment" +msgstr "Commenter" #: ../src/Gui/report.glade.h:3 -msgid "How to reproduce (in a few simple steps)" -msgstr "Comment reproduire (en quelques étapes simples)" +msgid "Following items will be sent" +msgstr "Les points suivants seront envoyés" + +#: ../src/Gui/report.glade.h:4 +msgid "How to reproduce (in a few simple steps)" +msgstr "Comment reproduire (en quelques étapes simples)" -#: ../src/Gui/report.glade.h:5 +#: ../src/Gui/report.glade.h:7 msgid "Send" msgstr "Envoyer" @@ -322,11 +334,11 @@ msgstr "Sélectionnez l'extension" msgid "Select database backend" msgstr "Sélectionnez le moteur de base de données" -#: ../src/Gui/SettingsDialog.py:165 +#: ../src/Gui/SettingsDialog.py:166 msgid "Remove this job" msgstr "Supprimer ce travail" -#: ../src/Gui/SettingsDialog.py:208 +#: ../src/Gui/SettingsDialog.py:210 msgid "Remove this action" msgstr "Supprimer cette action" @@ -339,104 +351,92 @@ msgid "Associated action" msgstr "Action associée" #: ../src/Gui/settings.glade.h:3 +msgid "Plugin details" +msgstr "Détails de l'extension" + +#: ../src/Gui/settings.glade.h:4 msgid "Plugin" msgstr "Extension" -#: ../src/Gui/settings.glade.h:4 +#: ../src/Gui/settings.glade.h:5 msgid "Time (or period)" msgstr "Durée (ou période)" -#: ../src/Gui/settings.glade.h:5 +#: ../src/Gui/settings.glade.h:6 msgid "Analyzers, Actions, Reporters" msgstr "Analyseurs, actions, rapporteurs" -#: ../src/Gui/settings.glade.h:6 +#: ../src/Gui/settings.glade.h:7 msgid "Author:" msgstr "Auteur :" -#: ../src/Gui/settings.glade.h:7 +#: ../src/Gui/settings.glade.h:8 msgid "Blacklisted packages: " msgstr "Paquets sur liste noire : " -#: ../src/Gui/settings.glade.h:8 +#: ../src/Gui/settings.glade.h:9 msgid "C_onfigure plugin" msgstr "C_onfiguration de l'extension" -#: ../src/Gui/settings.glade.h:9 +#: ../src/Gui/settings.glade.h:10 msgid "Check package GPG signature" msgstr "Vérification de la signature GPG du paquet" -#: ../src/Gui/settings.glade.h:10 +#: ../src/Gui/settings.glade.h:11 msgid "Common" msgstr "Commun" -#: ../src/Gui/settings.glade.h:11 +#: ../src/Gui/settings.glade.h:12 msgid "Cron" msgstr "Cron" -#: ../src/Gui/settings.glade.h:12 +#: ../src/Gui/settings.glade.h:13 msgid "Database backend: " msgstr "Moteur de base de données : " -#: ../src/Gui/settings.glade.h:13 -msgid "Edit blacklisted packages" -msgstr "Édition des paquets sur liste noire" - #: ../src/Gui/settings.glade.h:14 +msgid "Description:" +msgstr "Description :" + +#: ../src/Gui/settings.glade.h:15 msgid "GPG Keys" msgstr "Clés GPG" -#: ../src/Gui/settings.glade.h:15 +#: ../src/Gui/settings.glade.h:16 msgid "GPG keys: " msgstr "Clés GPG :" -#: ../src/Gui/settings.glade.h:16 +#: ../src/Gui/settings.glade.h:17 msgid "Global Settings" msgstr "Paramètres globaux" -#: ../src/Gui/settings.glade.h:17 +#: ../src/Gui/settings.glade.h:18 msgid "Max coredump storage size(MB):" msgstr "Taille de stockage coredump maximal (en Mo) :" -#: ../src/Gui/settings.glade.h:18 -msgid "Nothing selected" -msgstr "Aucune sélection" - #: ../src/Gui/settings.glade.h:19 -msgid "Plugin Details" -msgstr "Détails de l'extension" +msgid "Name:" +msgstr "Nom :" #: ../src/Gui/settings.glade.h:20 msgid "Settings" msgstr "Paramètres" #: ../src/Gui/settings.glade.h:21 -msgid "This function is not implemented yet!" -msgstr "Cette fonction n'est pas encore implémentée !" - -#: ../src/Gui/settings.glade.h:22 msgid "Version:" msgstr "Version :" -#: ../src/Gui/settings.glade.h:23 +#: ../src/Gui/settings.glade.h:22 msgid "Web Site:" msgstr "Site web :" -#: ../src/Gui/settings.glade.h:24 -msgid "gtk-add" -msgstr "gtk-add" - -#: ../src/Gui/settings.glade.h:25 +#: ../src/Gui/settings.glade.h:23 msgid "gtk-cancel" msgstr "gtk-cancel" -#: ../src/Gui/settings.glade.h:26 -msgid "gtk-close" -msgstr "gtk-close" - -#: ../src/Gui/settings.glade.h:28 -msgid "gtk-remove" -msgstr "gtk-remove" +#: ../src/Gui/settings.glade.h:24 +msgid "gtk-ok" +msgstr "gtk-ok" #: ../src/Gui/abrt.desktop.in.h:2 msgid "View and report application crashes" @@ -447,15 +447,15 @@ msgstr "Visualiser et signaler les plantages de l'application" msgid "A crash in package %s has been detected" msgstr "Un incident a été détecté dans le paquet %s" -#: ../src/Applet/Applet.cpp:253 +#: ../src/Applet/Applet.cpp:254 msgid "ABRT service is not running" msgstr "Le service ABRT n'est pas en cours d'exécution" -#: ../src/Applet/CCApplet.cpp:196 +#: ../src/Applet/CCApplet.cpp:204 msgid "Warning" msgstr "Avertissement" -#: ../src/Daemon/Daemon.cpp:520 +#: ../src/Daemon/Daemon.cpp:478 msgid "" "Report size exceeded the quota. Please check system's MaxCrashReportsSize " "value in abrt.conf." @@ -463,11 +463,13 @@ msgstr "" "La taille du rapport dépasse le quota. Veuillez vérifier la valeur " "MaxCrashReportsSize du système dans abrt.conf." -#: ../lib/Plugins/Bugzilla.cpp:202, c-format +#: ../lib/Plugins/Bugzilla.cpp:202 +#, c-format msgid "Bug is already reported: %i" msgstr "Le bogue est déjà signalé : %i" -#: ../lib/Plugins/Bugzilla.cpp:264, c-format +#: ../lib/Plugins/Bugzilla.cpp:264 +#, c-format msgid "New bug id: %i" msgstr "Nouvel ID de bogue : %i" @@ -499,31 +501,23 @@ msgstr "Déconnexion..." msgid "Getting local universal unique identification" msgstr "Obtention de l'UUID locale" -#: ../lib/Plugins/CCpp.cpp:257 -msgid "Getting backtrace..." -msgstr "Obtention du parcours arrière..." - -#: ../lib/Plugins/CCpp.cpp:566 ../lib/Plugins/CCpp.cpp:693 -msgid "Searching for debug-info packages..." -msgstr "Recherche de paquets debug-info..." +#: ../lib/Plugins/CCpp.cpp:258 +msgid "Generating backtrace" +msgstr "Génération du parcours arrière..." -#: ../lib/Plugins/CCpp.cpp:628 ../lib/Plugins/CCpp.cpp:727 -msgid "Downloading and installing debug-info packages..." -msgstr "Téléchargement et installation des paquets debug-info..." +#: ../lib/Plugins/CCpp.cpp:377 +msgid "Starting debuginfo installation" +msgstr "Démarrage de l'installation de debuginfo" -#: ../lib/Plugins/CCpp.cpp:832 +#: ../lib/Plugins/CCpp.cpp:527 msgid "Getting local universal unique identification..." msgstr "Obtention de l'UUID locale..." -#: ../lib/Plugins/CCpp.cpp:851 +#: ../lib/Plugins/CCpp.cpp:546 msgid "Getting global universal unique identification..." msgstr "Obtention de l'UUID globale..." -#: ../lib/Plugins/CCpp.cpp:896 -msgid "Starting report creation..." -msgstr "Lancement de la création de rapport..." - -#: ../lib/Plugins/CCpp.cpp:929 +#: ../lib/Plugins/CCpp.cpp:702 msgid "Skipping debuginfo installation" msgstr "Ignorer l'installation de debug-info" @@ -531,27 +525,31 @@ msgstr "Ignorer l'installation de debug-info" msgid "Creating and submitting a report..." msgstr "Création et envoi d'un rapport..." -#: ../lib/Plugins/Logger.cpp:65 -msgid "Creating a report..." -msgstr "Création d'un rapport..." +#: ../lib/Plugins/Logger.cpp:82 +#, c-format +msgid "Writing report to '%s'" +msgstr "Écriture du rapport à « %s »" -#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:384 +#: ../lib/Plugins/FileTransfer.cpp:63 ../lib/Plugins/FileTransfer.cpp:381 msgid "FileTransfer: URL not specified" msgstr "Transfert de fichier : URL non spécifié" -#: ../lib/Plugins/FileTransfer.cpp:67, c-format +#: ../lib/Plugins/FileTransfer.cpp:67 +#, c-format msgid "Sending archive %s to %s" msgstr "Envoi de l'archive %s vers %s" -#: ../lib/Plugins/FileTransfer.cpp:309 +#: ../lib/Plugins/FileTransfer.cpp:306 msgid "File Transfer: Creating a report..." msgstr "Transfert de fichier : Création d'un rapport" -#: ../lib/Plugins/FileTransfer.cpp:334, c-format +#: ../lib/Plugins/FileTransfer.cpp:331 +#, c-format msgid "Can't create and send an archive: %s" msgstr "Impossible de créer et d'envoyer une archive : %s" -#: ../lib/Plugins/FileTransfer.cpp:359, c-format +#: ../lib/Plugins/FileTransfer.cpp:356 +#, c-format msgid "Can't create and send an archive %s" msgstr "Impossible de créer et d'envoyer une archive %s" @@ -567,7 +565,8 @@ msgstr "Envoi d'un email..." msgid "Executing SOSreport plugin..." msgstr "Exécution de l'extension SOSreport..." -#: ../lib/Plugins/SOSreport.cpp:91, c-format +#: ../lib/Plugins/SOSreport.cpp:91 +#, c-format msgid "running sosreport: %s" msgstr "exécution de sosreport : %s" @@ -575,6 +574,42 @@ msgstr "exécution de sosreport : %s" msgid "done running sosreport" msgstr "exécution de sosreport terminée" +#~ msgid "Description" +#~ msgstr "Description" + +#~ msgid "Working..." +#~ msgstr "Traitement en cours..." + +#~ msgid "Edit blacklisted packages" +#~ msgstr "Édition des paquets sur liste noire" + +#~ msgid "Nothing selected" +#~ msgstr "Aucune sélection" + +#~ msgid "This function is not implemented yet!" +#~ msgstr "Cette fonction n'est pas encore implémentée !" + +#~ msgid "gtk-add" +#~ msgstr "gtk-add" + +#~ msgid "gtk-close" +#~ msgstr "gtk-close" + +#~ msgid "gtk-remove" +#~ msgstr "gtk-remove" + +#~ msgid "Searching for debug-info packages..." +#~ msgstr "Recherche de paquets debug-info..." + +#~ msgid "Downloading and installing debug-info packages..." +#~ msgstr "Téléchargement et installation des paquets debug-info..." + +#~ msgid "Starting report creation..." +#~ msgstr "Lancement de la création de rapport..." + +#~ msgid "Creating a report..." +#~ msgstr "Création d'un rapport..." + #~ msgid "Can't get username for uid %s" #~ msgstr "Impossible d'obtenir le nom d'utilisateur pour l'uid %s" -- cgit