diff options
Diffstat (limited to 'src/Daemon')
| -rw-r--r-- | src/Daemon/Daemon.cpp | 60 | ||||
| -rw-r--r-- | src/Daemon/MiddleWare.cpp | 51 | ||||
| -rw-r--r-- | src/Daemon/MiddleWare.h | 7 | ||||
| -rw-r--r-- | src/Daemon/Settings.cpp | 2 | ||||
| -rwxr-xr-x | src/Daemon/abrt-debuginfo-install | 249 |
5 files changed, 196 insertions, 173 deletions
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 67e72cca..53c44d3f 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -165,18 +165,6 @@ static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL return size; } -static bool analyzer_has_InformAllUsers(const char *analyzer_name) -{ - CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); - if (!analyzer) - return false; - map_plugin_settings_t settings = analyzer->GetSettings(); - map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers"); - if (it == settings.end()) - return false; - return string_to_bool(it->second.c_str()); -} - static void cron_delete_callback_data_cb(gpointer data) { cron_callback_data_t* cronDeleteCallbackData = static_cast<cron_callback_data_t*>(data); @@ -388,23 +376,24 @@ static void FindNewDumps(const char* pPath) switch (res) { case MW_OK: - VERB1 log("Saving into database (%s)", itt->c_str()); + VERB1 log("Saving %s into database", itt->c_str()); RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str()); break; case MW_IN_DB: - VERB1 log("Already saved in database (%s)", itt->c_str()); + VERB1 log("%s is already saved in database", itt->c_str()); break; case MW_REPORTED: case MW_OCCURED: + VERB1 log("Already saved crash %s, deleting", itt->c_str()); + DeleteDebugDumpDir(itt->c_str()); + break; case MW_BLACKLISTED: case MW_CORRUPTED: case MW_PACKAGE_ERROR: case MW_GPG_ERROR: case MW_FILE_ERROR: default: -//Perhaps corrupted & bad needs to be logged unconditionally, -//already saved one - only on VERB1 - VERB1 log("Corrupted, bad or already saved crash, deleting"); + log("Corrupted or bad crash %s (res:%d), deleting", itt->c_str(), (int)res); DeleteDebugDumpDir(itt->c_str()); break; } @@ -556,7 +545,6 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin : crashinfo[CD_UID][CD_CONTENT].c_str(); g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT].c_str(), uid_str); } - //DeleteDebugDumpDir(fullname.c_str()); break; case MW_BLACKLISTED: case MW_CORRUPTED: @@ -670,29 +658,36 @@ static void start_syslog_logging() logmode = LOGMODE_SYSLOG; } -static void ensure_root_writable_dir(const char *dir) +static void ensure_writable_dir(const char *dir, mode_t mode, const char *group) { struct stat sb; - if (mkdir(dir, 0755) != 0 && errno != EEXIST) + if (mkdir(dir, mode) != 0 && errno != EEXIST) perror_msg_and_die("Can't create '%s'", dir); if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode)) error_msg_and_die("'%s' is not a directory", dir); - if ((sb.st_uid != 0 || sb.st_gid != 0) && chown(dir, 0, 0) != 0) + + struct group *gr = getgrnam(group); + if (!gr) + perror_msg_and_die("Can't find group '%s'", group); + + 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:0 on '%s'", dir); - /* We can't allow anyone to create dumps: otherwise users can flood - * 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 */ - if ((sb.st_mode & 07777) != 0755 && chmod(dir, 0755) != 0) - perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", dir); + if ((sb.st_mode & 07777) != mode && chmod(dir, mode) != 0) + perror_msg_and_die("Can't set mode %o on '%s'", mode, dir); } static void sanitize_dump_dir_rights() { - ensure_root_writable_dir(DEBUG_DUMPS_DIR); - ensure_root_writable_dir(DEBUG_DUMPS_DIR"-di"); /* debuginfo cache */ - ensure_root_writable_dir(VAR_RUN"/abrt"); /* temp dir */ + /* We can't allow anyone to create dumps: otherwise users can flood + * 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"); + /* debuginfo cache */ + ensure_writable_dir(DEBUG_DUMPS_DIR"-di", 0755, "root"); + /* temp dir */ + ensure_writable_dir(VAR_RUN"/abrt", 0755, "root"); } int main(int argc, char** argv) @@ -806,11 +801,6 @@ int main(int argc, char** argv) pMainloop = g_main_loop_new(NULL, FALSE); /* Watching DEBUG_DUMPS_DIR for new files... */ VERB1 log("Initializing inotify"); -// Enabled again since we have new abrt-pyhook-helper, remove comment when verified to work - /* FIXME: python hook runs with ordinary user privileges, - * so it fails if everyone doesn't have write acces - * to DEBUG_DUMPS_DIR - */ sanitize_dump_dir_rights(); errno = 0; int inotify_fd = inotify_init(); diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 6a635642..0bc358e1 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -456,10 +456,9 @@ void DeleteDebugDumpDir(const char *pDebugDumpDir) std::string DeleteCrashInfo(const char *pUUID, const char *pUID) { - database_row_t row; CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->Delete(pUUID, pUID); database->DisConnect(); @@ -573,6 +572,21 @@ static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable, return MW_OK; } +bool analyzer_has_InformAllUsers(const char *analyzer_name) +{ + CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); + if (!analyzer) + { + VERB1 log("Strange, asked for analyzer %s but it doesn't exist?", analyzer_name); + return false; + } + map_plugin_settings_t settings = analyzer->GetSettings(); + map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers"); + if (it == settings.end()) + return false; + return string_to_bool(it->second.c_str()); +} + /** * Execute all action plugins, which are associated to * particular analyzer plugin. @@ -621,14 +635,12 @@ static mw_result_t SaveDebugDumpToDatabase(const char *pUUID, const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { - mw_result_t res; CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); database->Insert(pUUID, pUID, pDebugDumpDir, pTime); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); - res = GetCrashInfo(pUUID, pUID, pCrashInfo); + mw_result_t res = GetCrashInfo(pUUID, pUID, pCrashInfo); if (row.m_sReported == "1") { log("Crash is already reported"); @@ -646,29 +658,19 @@ std::string getDebugDumpDir(const char *pUUID, const char *pUID) { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); return row.m_sDebugDumpDir; } -mw_result_t SaveDebugDump(const char *pDebugDumpDir) -{ - map_crash_info_t info; - return SaveDebugDump(pDebugDumpDir, info); -} - mw_result_t SaveDebugDump(const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { - std::string lUUID; std::string UID; std::string time; std::string analyzer; std::string executable; - mw_result_t res; - try { CDebugDump dd; @@ -692,15 +694,17 @@ mw_result_t SaveDebugDump(const char *pDebugDumpDir, { return MW_IN_DB; } - res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir); + mw_result_t res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir); if (res != MW_OK) { return res; } - lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir); - - return SaveDebugDumpToDatabase(lUUID.c_str(), UID.c_str(), time.c_str(), pDebugDumpDir, pCrashInfo); + std::string lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir); + const char *uid_str = analyzer_has_InformAllUsers(analyzer.c_str()) + ? "-1" + : UID.c_str(); + return SaveDebugDumpToDatabase(lUUID.c_str(), uid_str, time.c_str(), pDebugDumpDir, pCrashInfo); } mw_result_t GetCrashInfo(const char *pUUID, @@ -709,16 +713,14 @@ mw_result_t GetCrashInfo(const char *pUUID, { pCrashInfo.clear(); CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); std::string package; std::string executable; std::string description; std::string analyzer; - try { CDebugDump dd; @@ -737,6 +739,7 @@ mw_result_t GetCrashInfo(const char *pUUID, } return MW_ERROR; } + add_crash_data_to_crash_info(pCrashInfo, CD_EXECUTABLE, executable); add_crash_data_to_crash_info(pCrashInfo, CD_PACKAGE, package); add_crash_data_to_crash_info(pCrashInfo, CD_DESCRIPTION, description); diff --git a/src/Daemon/MiddleWare.h b/src/Daemon/MiddleWare.h index 0671dd02..ac042def 100644 --- a/src/Daemon/MiddleWare.h +++ b/src/Daemon/MiddleWare.h @@ -120,12 +120,6 @@ void DeleteDebugDumpDir(const char *pDebugDumpDir); std::string DeleteCrashInfo(const char *pUUID, const char *pUID); /** - * Saves debugdump into database. - * @param pDebugDumpDir A debugdump directory. - * @return It return results of operation. See mw_result_t. - */ -mw_result_t SaveDebugDump(const char *pDebugDumpDir); -/** * Saves debugdump into database. If saving is successful, * it fills crash info. * @param pDebugDumpDir A debugdump directory. @@ -171,5 +165,6 @@ void AddAnalyzerActionOrReporter(const char *pAnalyzer, void AddActionOrReporter(const char *pActionOrReporter, const char *pArgs); +bool analyzer_has_InformAllUsers(const char *analyzer_name); #endif /*MIDDLEWARE_H_*/ diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp index d9c9a98b..cefd35a4 100644 --- a/src/Daemon/Settings.cpp +++ b/src/Daemon/Settings.cpp @@ -132,7 +132,7 @@ static void ParseCommon() map_string_t::const_iterator end = s_mapSectionCommon.end(); if (it != end) { - g_settings_bOpenGPGCheck = it->second == "yes"; + g_settings_bOpenGPGCheck = string_to_bool(it->second.c_str()); } it = s_mapSectionCommon.find("OpenGPGPublicKeys"); if (it != end) diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index 6070b74d..b3d72922 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -80,22 +80,39 @@ count_words() { echo $# } -cleanup_and_report_missing() { -# Which debuginfo files are still missing, including those we just unpacked? - missing_build_ids=`for build_id in $build_ids; do +print_missing_build_ids() { + for build_id in $build_ids; do build_id1=${build_id:0:2} build_id2=${build_id:2} file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" test -f "/$file" && continue test -f "$cachedir/$file" && continue echo -n "$build_id " - done` + done +} + +print_missing_debuginfos() { + for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then + test -f "$cachedir/$file" && continue + fi + test -f "/$file" && continue + echo -n "/$file " + done +} + +cleanup_and_report_missing() { +# Which debuginfo files are still missing, including those we just unpacked? + missing_build_ids=`print_missing_build_ids` $debug && echo "missing_build_ids:$missing_build_ids" # If cachedir is specified, tempdir is just a staging area. Delete it if test x"$cachedir" != x""; then $debug && echo "Removing $tempdir" - rm -rf "$tempdir" + $debug || rm -rf "$tempdir" fi for missing in $missing_build_ids; do @@ -105,6 +122,98 @@ cleanup_and_report_missing() { test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found" } +# $1: iteration (1,2...) +print_package_names() { + # We'll run something like: + # yum --enablerepo='*debuginfo*' --quiet provides \ + # /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ + # /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... + local yumopts="" + if test x"$1" = x"1"; then + yumopts="-C" + echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from cache" >&2 + else + echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list" >&2 + fi + local cmd="yum $yumopts --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files" + echo "$cmd" >"yum_provides.$1.OUT" + local yum_provides_OUT=`$cmd 2>&1` + local err=$? + printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >>"yum_provides.$1.OUT" + test $err = 0 || exit 2 + + # The output is pretty machine-unfriendly: + # glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc + # Repo : rawhide-debuginfo + # Matched from: + # Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug + # + # 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus + # Repo : updates-debuginfo + # Matched from: + # Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug + # Need to massage it a lot. + # There can be duplicates (one package may provide many debuginfos). + printf "%s\n" "$yum_provides_OUT" \ + | grep -- -debuginfo- \ + | sed 's/^[0-9]*://' \ + | sed -e 's/ .*//' -e 's/:.*//' \ + | sort | uniq | xargs +} + +download_packages() { + ## Download with one command (too silent): + ## Redirecting, since progress bar stuff only messes up our output + ##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 + ##err=$? + ##echo "exitcode:$err" >>yumdownloader.OUT + ##test $err = 0 || exit 2 + >yumdownloader.OUT + i=1 + for pkg in $packages; do + echo "Download $i/$num_packages: $pkg" + echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT + yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1 + err=$? + echo "exitcode:$err" >>yumdownloader.OUT + echo >>yumdownloader.OUT + test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; } + : $((i++)) + done + + for f in *.rpm; do + # Happens if no .rpm's were downloaded (yumdownloader problem) + # In this case, $f is the literal "*.rpm" string + test -f "$f" || exit 2 + echo "Unpacking: $f" + echo "Processing: $f" >>unpack.OUT + rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 + done + + # Copy debuginfo files to cachedir + if test x"$cachedir" != x"" && test -d "$cachedir"; then + for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} + + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + + test -f "/$file" && continue + test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue + + if test -f "$file"; then + # file is one of those we just installed. + # Cache it if cachedir is specified. + mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" + # Note: this does not preserve symlinks. This is intentional + $debug && echo Copying2 "$file" to "$cachedir/$file" >&2 + cp --remove-destination "$file" "$cachedir/$file" + continue + fi + done + fi +} + # eu-unstrip output example: # 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] @@ -138,113 +247,39 @@ build_ids=`printf "%s\n" "$eu_unstrip_OUT" \ done | sort | uniq | xargs` $debug && echo "build_ids:$build_ids" -# Which debuginfo files are missing? -missing_debuginfo_files=`for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then - test -f "$cachedir/$file" && continue - fi - test -f "/$file" && continue - echo -n "/$file " -done` -$debug && echo "missing_debuginfo_files:$missing_debuginfo_files" - -if test x"$missing_debuginfo_files" = x""; then - cleanup_and_report_missing - exit 0 -fi - -# We'll run something like: -# yum --enablerepo='*debuginfo*' --quiet provides \ -# /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ -# /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... -echo "Determining list of packages for `count_words $missing_debuginfo_files` missing debuginfos" -yum_provides_OUT=`yum --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files 2>&1` -err=$? -printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >yum_provides.OUT -test $err = 0 || exit 2 +# We try to not run yum without -C unless absolutely necessary. +# Therefore we loop. yum is run by print_package_names function, +# on first iteration it is run with -C, on second - without, +# which usually causes yum to download updated filelists, +# which in turn takes several minutes and annoys users. +iter=0 +while true; do + : $((iter++)) + test $iter -gt 2 && break -# The output is pretty machine-unfriendly: -# glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc -# Repo : rawhide-debuginfo -# Matched from: -# Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug -# -# 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus -# Repo : updates-debuginfo -# Matched from: -# Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug -# Need to massage it a lot. -# There can be duplicates (one package may provide many debuginfos). -packages=`printf "%s\n" "$yum_provides_OUT" \ -| grep -- -debuginfo- \ -| sed 's/^[0-9]*://' \ -| sed -e 's/ .*//' -e 's/:.*//' \ -| sort | uniq | xargs` -$debug && echo "packages:$packages" - -# yum may return "" here if it found no packages (say, if coredump is from a new, -# unreleased package fresh from koji). -if test x"$packages" = x""; then - cleanup_and_report_missing - exit 1 -fi - -num_packages=`count_words $packages` -echo "Downloading $num_packages packages" -## Download with one command (too silent): -## Redirecting, since progress bar stuff only messes up our output -##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 -##err=$? -##echo "exitcode:$err" >>yumdownloader.OUT -##test $err = 0 || exit 2 ->yumdownloader.OUT -i=1 -for pkg in $packages; do - echo "Download $i/$num_packages: $pkg" - echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT - yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1 - err=$? - echo "exitcode:$err" >>yumdownloader.OUT - echo >>yumdownloader.OUT - test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; } - : $((i++)) -done + # Analyze $build_ids and check which debuginfos are present + missing_debuginfo_files=`print_missing_debuginfos` + $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" -for f in *.rpm; do - # Happens if no .rpm's were downloaded (yumdownloader problem) - # In this case, $f is the literal "*.rpm" string - test -f "$f" || exit 2 - echo "Unpacking: $f" - echo "Processing: $f" >>unpack.OUT - rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 -done + if test x"$missing_debuginfo_files" = x""; then + break + fi -# Copy debuginfo files to cachedir -if test x"$cachedir" != x"" && test -d "$cachedir"; then - for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} + # Map $missing_debuginfo_files to package names. + # yum is run here. + packages=`print_package_names $iter` + $debug && echo "packages ($iter):$packages" - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + # yum may return "" here if it found no packages (say, if coredump + # is from a new, unreleased package fresh from koji). + if test x"$packages" = x""; then + continue + fi - test -f "/$file" && continue - test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue - - if test -f "$file"; then - # file is one of those we just installed. - # Cache it if cachedir is specified. - mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" - # Note: this does not preserve symlinks. This is intentional - $debug && echo Copying2 "$file" to "$cachedir/$file" >&2 - cp --remove-destination "$file" "$cachedir/$file" - continue - fi - done -fi -$debug && echo "missing_build_ids:$missing_build_ids" + num_packages=`count_words $packages` + echo "Downloading $num_packages packages" + download_packages +done cleanup_and_report_missing |
