summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-12-18 19:12:50 +0100
committerKarel Klic <kklic@redhat.com>2009-12-18 19:12:50 +0100
commite7661d7e411172ddad8838040ded025ad6bfbb14 (patch)
treef2451b553b4fcf959bd2bfc29172f9fb855e5fdd /src
parentce1904e24b576a7356488852a240d777717b2598 (diff)
parent46b2fb8df8d4e025f5bbdd9f53be1f658a9e82c6 (diff)
downloadabrt-e7661d7e411172ddad8838040ded025ad6bfbb14.tar.gz
abrt-e7661d7e411172ddad8838040ded025ad6bfbb14.tar.xz
abrt-e7661d7e411172ddad8838040ded025ad6bfbb14.zip
Merge branch 'master' of git://git.fedorahosted.org/git/abrt
Diffstat (limited to 'src')
-rw-r--r--src/Applet/CCApplet.cpp2
-rw-r--r--src/CLI/ABRTSocket.cpp12
-rw-r--r--src/Daemon/Daemon.cpp19
-rw-r--r--src/Daemon/MiddleWare.cpp77
-rw-r--r--src/Daemon/PluginManager.cpp6
-rw-r--r--src/Daemon/Settings.cpp2
-rwxr-xr-xsrc/Daemon/abrt-debuginfo-install79
-rw-r--r--src/Gui/CCMainWindow.py5
-rw-r--r--src/Hooks/CCpp.cpp322
-rw-r--r--src/Hooks/abrt-hook-python.cpp20
-rw-r--r--src/Hooks/abrt_exception_handler.py.in1
-rw-r--r--src/Hooks/sitecustomize.py42
12 files changed, 274 insertions, 313 deletions
diff --git a/src/Applet/CCApplet.cpp b/src/Applet/CCApplet.cpp
index 5d13ab8..f9212b2 100644
--- a/src/Applet/CCApplet.cpp
+++ b/src/Applet/CCApplet.cpp
@@ -320,7 +320,7 @@ void CApplet::animate_icon()
if (m_iAnimator == 0)
{
m_iAnimator = g_timeout_add(100, update_icon, this);
- m_iAnimCountdown = 10 * 60; /* 60 sec */
+ m_iAnimCountdown = 10 * 30; /* 30 sec */
}
}
diff --git a/src/CLI/ABRTSocket.cpp b/src/CLI/ABRTSocket.cpp
index d31c7a4..1353134 100644
--- a/src/CLI/ABRTSocket.cpp
+++ b/src/CLI/ABRTSocket.cpp
@@ -13,7 +13,17 @@ CABRTSocket::CABRTSocket() : m_nSocket(-1)
CABRTSocket::~CABRTSocket()
{
- Disconnect();
+ /* Paranoia. In C++, destructor will abort() if it was called while unwinding
+ * the stack and it throws an exception.
+ */
+ try
+ {
+ Disconnect();
+ }
+ catch (...)
+ {
+ error_msg_and_die("Internal error");
+ }
}
void CABRTSocket::Send(const std::string& pMessage)
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp
index c6cae5d..8038f75 100644
--- a/src/Daemon/Daemon.cpp
+++ b/src/Daemon/Daemon.cpp
@@ -110,7 +110,7 @@ typedef struct cron_callback_data_t
} cron_callback_data_t;
-static uint8_t s_sig_caught; /* must be one byte */
+static volatile sig_atomic_t s_sig_caught;
static int s_signal_pipe[2];
static int s_signal_pipe_write = -1;
static unsigned s_timeout;
@@ -216,14 +216,14 @@ static int SetUpCron()
std::string sM = "";
sH = it_c->first.substr(0, pos);
- nH = atoi(sH.c_str());
+ nH = xatou(sH.c_str());
nH = nH > 23 ? 23 : nH;
nH = nH < 0 ? 0 : nH;
nM = nM > 59 ? 59 : nM;
nM = nM < 0 ? 0 : nM;
timeout += nH * 60 * 60;
sM = it_c->first.substr(pos + 1);
- nM = atoi(sM.c_str());
+ nM = xatou(sM.c_str());
timeout += nM * 60;
}
else
@@ -231,7 +231,7 @@ static int SetUpCron()
std::string sS = "";
sS = it_c->first;
- nS = atoi(sS.c_str());
+ nS = xatou(sS.c_str());
nS = nS <= 0 ? 1 : nS;
timeout = nS;
}
@@ -399,10 +399,15 @@ static int Lock()
static void handle_fatal_signal(int signo)
{
- s_sig_caught = signo;
- VERB3 log("Got signal %d", signo);
+ // Enable for debugging only, malloc/printf are unsafe in signal handlers
+ //VERB3 log("Got signal %d", signo);
+
+ uint8_t l_sig_caught;
+ s_sig_caught = l_sig_caught = signo;
+ /* Using local copy of s_sig_caught so that concurrent signal
+ * won't change it under us */
if (s_signal_pipe_write >= 0)
- write(s_signal_pipe_write, &s_sig_caught, 1);
+ write(s_signal_pipe_write, &l_sig_caught, 1);
}
/* Signal pipe handler */
diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp
index b597a41..6b8bfcc 100644
--- a/src/Daemon/MiddleWare.cpp
+++ b/src/Daemon/MiddleWare.cpp
@@ -477,7 +477,7 @@ report_status_t Report(const map_crash_report_t& pCrashReport,
if (pUID != "")
{
- home = get_home_dir(atoi(pUID.c_str()));
+ home = get_home_dir(xatoi_u(pUID.c_str()));
if (home != "")
{
oldSettings = reporter->GetSettings();
@@ -563,11 +563,38 @@ void LoadOpenGPGPublicKey(const char* key)
* @param pDebugDumpDir A debugdump dir containing all necessary data.
* @return It return results of operation. See mw_result_t.
*/
-static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable,
- const char *pDebugDumpDir)
+static char *get_argv1_if_full_path(const char* cmdline)
+{
+ char *argv1 = (char*) strchr(cmdline, ' ');
+ if (argv1 != NULL)
+ {
+ /* we found space in cmdline, so it might contain
+ * path to some script like:
+ * /usr/bin/python /usr/bin/system-control-network
+ */
+ argv1++;
+ /* if the string following the space doesn't start
+ * with '/' it's probably not a full path to script
+ * and we can't use it to determine the package name
+ */
+ if (*argv1 != '/')
+ {
+ return NULL;
+ }
+ int len = strchrnul(argv1, ' ') - argv1;
+ /* cut the cmdline arguments */
+ argv1 = xstrndup(argv1, len);
+ }
+ return argv1;
+}
+static mw_result_t SavePackageDescriptionToDebugDump(
+ const char *pExecutable,
+ const char *cmdline,
+ const char *pDebugDumpDir)
{
std::string package;
std::string packageName;
+ std::string scriptName; /* only if "interpreter /path/to/script" */
if (strcmp(pExecutable, "kernel") == 0)
{
@@ -582,6 +609,42 @@ static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable,
return MW_PACKAGE_ERROR;
}
+ /* Check well-known interpreter names */
+
+ const char *basename = strrchr(pExecutable, '/');
+ if (basename) basename++; else basename = pExecutable;
+
+ /* Add "perl" and such as needed */
+ if (strcmp(basename, "python") == 0)
+ {
+// TODO: we don't verify that python executable is not modified
+// or that python package is properly signed
+// (see CheckFingerprint/CheckHash below)
+
+ /* Try to find package for the script by looking at argv[1].
+ * This will work only of the cmdline contains the whole path.
+ * Example: python /usr/bin/system-control-network
+ */
+ char *script_name = get_argv1_if_full_path(cmdline);
+ if (script_name)
+ {
+ char *script_pkg = GetPackage(script_name);
+ if (script_pkg)
+ {
+ /* There is a well-formed script name in argv[1],
+ * and it does belong to some package.
+ * Replace interpreter's rpm_pkg and pExecutable
+ * with data pertaining to the script.
+ */
+ free(rpm_pkg);
+ rpm_pkg = script_pkg;
+ scriptName = script_name;
+ pExecutable = scriptName.c_str();
+ }
+ free(script_name);
+ }
+ }
+
package = rpm_pkg;
packageName = package.substr(0, package.rfind("-", package.rfind("-") - 1));
VERB2 log("Package:'%s' short:'%s'", rpm_pkg, packageName.c_str());
@@ -610,10 +673,7 @@ static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable,
}
std::string description = GetDescription(packageName.c_str());
-//TODO: if executable in /usr/bin/python, /bin/sh and such,
-//we need to extract component using argv[1]
std::string component = GetComponent(pExecutable);
-
try
{
CDebugDump dd;
@@ -788,6 +848,7 @@ mw_result_t SaveDebugDump(const char *pDebugDumpDir,
std::string time;
std::string analyzer;
std::string executable;
+ std::string cmdline;
try
{
CDebugDump dd;
@@ -796,6 +857,7 @@ mw_result_t SaveDebugDump(const char *pDebugDumpDir,
dd.LoadText(FILENAME_UID, UID);
dd.LoadText(FILENAME_ANALYZER, analyzer);
dd.LoadText(FILENAME_EXECUTABLE, executable);
+ dd.LoadText(FILENAME_CMDLINE, cmdline);
}
catch (CABRTException& e)
{
@@ -811,7 +873,8 @@ mw_result_t SaveDebugDump(const char *pDebugDumpDir,
{
return MW_IN_DB;
}
- mw_result_t res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir);
+
+ mw_result_t res = SavePackageDescriptionToDebugDump(executable.c_str(), cmdline.c_str(), pDebugDumpDir);
if (res != MW_OK)
{
return res;
diff --git a/src/Daemon/PluginManager.cpp b/src/Daemon/PluginManager.cpp
index 82f22e8..b6a8b15 100644
--- a/src/Daemon/PluginManager.cpp
+++ b/src/Daemon/PluginManager.cpp
@@ -391,7 +391,7 @@ void CPluginManager::SetPluginSettings(const char *pName,
return;
}
- std::string home = get_home_dir(atoi(pUID.c_str()));
+ std::string home = get_home_dir(xatoi_u(pUID.c_str()));
if (home == "")
{
return;
@@ -399,7 +399,7 @@ void CPluginManager::SetPluginSettings(const char *pName,
std::string confDir = home + "/.abrt";
std::string confPath = confDir + "/" + pName + "."PLUGINS_CONF_EXTENSION;
- uid_t uid = atoi(pUID.c_str());
+ uid_t uid = xatoi_u(pUID.c_str());
struct passwd* pw = getpwuid(uid);
gid_t gid = pw ? pw->pw_gid : uid;
@@ -461,7 +461,7 @@ map_plugin_settings_t CPluginManager::GetPluginSettings(const char *pName,
/*
if (abrt_plugin->second->GetType() == REPORTER)
{
- std::string home = get_home_dir(atoi(pUID.c_str()));
+ std::string home = get_home_dir(xatoi_u(pUID.c_str()));
if (home != "")
{
LoadPluginSettings(home + "/.abrt/" + pName + "."PLUGINS_CONF_EXTENSION, ret);
diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp
index 327851f..d89bebf 100644
--- a/src/Daemon/Settings.cpp
+++ b/src/Daemon/Settings.cpp
@@ -176,7 +176,7 @@ static void ParseCommon()
it = s_mapSectionCommon.find("MaxCrashReportsSize");
if (it != end)
{
- g_settings_nMaxCrashReportsSize = atoi(it->second.c_str());
+ g_settings_nMaxCrashReportsSize = xatoi_u(it->second.c_str());
}
it = s_mapSectionCommon.find("ActionsAndReporters");
if (it != end)
diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install
index 6278b63..dcd3add 100755
--- a/src/Daemon/abrt-debuginfo-install
+++ b/src/Daemon/abrt-debuginfo-install
@@ -21,8 +21,7 @@
# Output goes to GUI as debuginfo install log. The script should be careful
# to give useful, but not overly cluttered info to stdout.
# Additionally, abrt daemon handles "MISSING:xxxx" messages specially:
-# xxxx will be prepended to backtrace. This is used to inform about
-# missing debuginfos.
+# it is used to inform about missing debuginfos.
#
# Exitcodes:
# 0 - all debuginfos are installed
@@ -46,36 +45,22 @@
# For better debuggability, eu_unstrip.OUT, yum_provides.OUT etc files
# are saved in TEMPDIR, and TEMPDIR is not deleted if we exit with exitcode 2
# ("serious problem").
-#
-# In the future, we may want to use a separate CACHEDIR (say, /var/cache/abrt-di)
-# and use it with this gdb command:
-# set debug-file-directory /usr/lib/debug/.build-id:CACHEDIR/usr/lib/debug/.build-id
-# but current gdb can't handle DIR1:DIR2.
-# So, currently we are called with CACHEDIR set to "/", and don't pass
-# "set debug-file-directory" to gdb.
-# This is ugly, since it messes up /usr/lib/debug/.build-id over time
-# by piling up debuginfos there without any means to control their amount,
-# but it's the only way to make it work with current gdb.
-
-
-core=$1
-tempdir=$2
+
+
+core="$1"
+tempdir="$2"
debuginfodirs="${3//:/ }"
cachedir="${3%%:*}"
debug=false
-exec 2>&1
-
-test -f "$core" || exit 2
-# cachedir is optional
-test x"$cachedir" = x"" || test -d "$cachedir" || exit 2
-# tempdir must not exist
-test -e "$tempdir" && exit 2
-mkdir -- "$tempdir" || exit 2
-cd "$tempdir" || exit 2
-$debug && echo "Installing rpms to $tempdir"
+# stderr may be used for status messages too
+exec 2>&1
+error_msg_and_die() {
+ echo "$*"
+ exit 2
+}
count_words() {
echo $#
@@ -92,6 +77,9 @@ print_missing_build_ids() {
build_id2=${build_id:2}
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
test -f "/$file" && continue
+ # On 2nd pass, we may already have some debuginfos in tempdir
+ test -f "$tempdir/$file" && continue
+ # Check cachedir if we have one
for d in $debuginfodirs; do
test -f "$d/$file" && continue 2
done
@@ -99,6 +87,7 @@ print_missing_build_ids() {
done
}
+# Note: it is run in `backticks`, use >&2 for error messages
print_missing_debuginfos() {
local build_id
local build_id1
@@ -110,6 +99,9 @@ print_missing_debuginfos() {
build_id2=${build_id:2}
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
test -f "/$file" && continue
+ # On 2nd pass, we may already have some debuginfos in tempdir
+ test -f "$tempdir/$file" && continue
+ # Check cachedir if we have one
if test x"$cachedir" != x""; then
for d in $debuginfodirs; do
test -f "$d/$file" && continue 2
@@ -138,6 +130,7 @@ cleanup_and_report_missing() {
}
# $1: iteration (1,2...)
+# Note: it is run in `backticks`, use >&2 for error messages
print_package_names() {
# We'll run something like:
# yum --enablerepo=*debuginfo* --quiet provides \
@@ -154,8 +147,9 @@ print_package_names() {
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
+ 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:
+`head yum_provides.$1.OUT`" >&2
# The output is pretty machine-unfriendly:
# glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc
@@ -190,7 +184,7 @@ download_packages() {
##yumdownloader --enablerepo=*debuginfo* --quiet $packages >yumdownloader.OUT 2>&1
##err=$?
##echo "exitcode:$err" >>yumdownloader.OUT
- ##test $err = 0 || exit 2
+ ##test $err = 0 || error_msg_and_die ...
>yumdownloader.OUT
i=1
for pkg in $packages; do
@@ -207,10 +201,11 @@ download_packages() {
for file in *.rpm; do
# Happens if no .rpm's were downloaded (yumdownloader problem)
# In this case, $f is the literal "*.rpm" string
- test -f "$file" || exit 2
+ test -f "$file" || error_msg_and_die "not a rpm file: '$file'"
echo "Unpacking: $file"
echo "Processing: $file" >>unpack.OUT
rpm2cpio <"$file" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1
+#TODO: error check?
done
# Copy debuginfo files to cachedir
@@ -235,6 +230,7 @@ download_packages() {
# Note: this does not preserve symlinks. This is intentional
$debug && echo Copying "$file" to "$cachedir/$file" >&2
cp --remove-destination "$file" "$cachedir/$file"
+#TODO: error check?
continue
fi
done
@@ -242,6 +238,18 @@ download_packages() {
}
+# Sanity checking
+test -f "$core" || error_msg_and_die "not a file: '$core'"
+# cachedir is optional
+test x"$cachedir" = x"" || test -d "$cachedir" || error_msg_and_die "bad cachedir '$cachedir'"
+# tempdir must not exist
+test -e "$tempdir" && error_msg_and_die "tempdir exists: '$tempdir'"
+
+mkdir -- "$tempdir" || exit 2
+cd "$tempdir" || exit 2
+$debug && echo "Installing rpms to $tempdir"
+
+
# eu-unstrip output example:
# 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
# or
@@ -254,8 +262,10 @@ echo "Getting list of build IDs"
# eu-unstrip: /var/cache/abrt/ccpp-1256301004-2754/coredump: Callback returned failure
eu_unstrip_OUT=`eu-unstrip "--core=$core" -n 2>eu_unstrip.ERR`
err=$?
-printf "%s\nexitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT
-test $err = 0 || exit 2
+printf "%s\neu-unstrip exitcode:%s\n" "$eu_unstrip_OUT" $err >eu_unstrip.OUT
+test $err = 0 || error_msg_and_die "eu-unstrip exited with $err:
+`cat eu_unstrip.ERR`
+`head eu_unstrip.OUT`"
# Get space-separated list of all build-ids
# There can be duplicates (observed in real world)
@@ -283,6 +293,8 @@ iter=0
while test $((++iter)) -le 2; do
# Analyze $build_ids and check which debuginfos are present
missing_debuginfo_files=`print_missing_debuginfos`
+ # Did print_missing_debuginfos fail?
+ test $? = 0 || exit 2
$debug && echo "missing_debuginfo_files:$missing_debuginfo_files"
test x"$missing_debuginfo_files" = x"" && break
@@ -290,6 +302,8 @@ while test $((++iter)) -le 2; do
# Map $missing_debuginfo_files to package names.
# yum is run here.
packages=`print_package_names $iter`
+ # Did print_package_names fail?
+ test $? = 0 || exit 2
$debug && echo "packages ($iter):$packages"
# yum may return "" here if it found no packages (say, if coredump
@@ -304,4 +318,5 @@ done
cleanup_and_report_missing
test x"$missing_build_ids" != x"" && exit 1
+echo "All needed debuginfos are present"
exit 0
diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py
index e429908..8544b24 100644
--- a/src/Gui/CCMainWindow.py
+++ b/src/Gui/CCMainWindow.py
@@ -167,7 +167,10 @@ class MainWindow():
self.wTree.get_widget("lStatus").set_text(message)
buff = gtk.TextBuffer()
buff.set_text(self.updates)
- self.wTree.get_widget("tvUpdates").set_buffer(buff)
+ end = buff.get_insert()
+ tvUpdates = self.wTree.get_widget("tvUpdates")
+ tvUpdates.set_buffer(buff)
+ tvUpdates.scroll_mark_onscreen(end)
# call to update the progressbar
def progress_update_cb(self, *args):
diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp
index fd789cf..3a13358 100644
--- a/src/Hooks/CCpp.cpp
+++ b/src/Hooks/CCpp.cpp
@@ -18,25 +18,14 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
-/* Make all file ops "large" and make off_t 64-bit.
- * No need to use O_LARGEFILE anywhere
- */
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _FILE_OFFSET_BITS 64
-
#include "abrtlib.h"
#include "DebugDump.h"
#include "ABRTException.h"
#include <syslog.h>
#define FILENAME_EXECUTABLE "executable"
-#define FILENAME_CMDLINE "cmdline"
#define FILENAME_COREDUMP "coredump"
-#define VAR_RUN_PID_FILE VAR_RUN"/abrt.pid"
-
using namespace std;
static char* malloc_readlink(const char *linkname)
@@ -69,157 +58,42 @@ static char* get_cwd(pid_t pid)
return malloc_readlink(buf);
}
-static char *append_escaped(char *start, const char *s)
-{
- char hex_char_buf[] = "\\x00";
-
- *start++ = ' ';
- char *dst = start;
- const unsigned char *p = (unsigned char *)s;
-
- while (1)
- {
- const unsigned char *old_p = p;
- while (*p > ' ' && *p <= 0x7e && *p != '\"' && *p != '\'' && *p != '\\')
- p++;
- if (dst == start)
- {
- if (p != (unsigned char *)s && *p == '\0')
- {
- /* entire word does not need escaping and quoting */
- strcpy(dst, s);
- dst += strlen(s);
- return dst;
- }
- *dst++ = '\'';
- }
-
- strncpy(dst, s, (p - old_p));
- dst += (p - old_p);
-
- if (*p == '\0')
- {
- *dst++ = '\'';
- *dst = '\0';
- return dst;
- }
- const char *a;
- switch (*p)
- {
- case '\r': a = "\\r"; break;
- case '\n': a = "\\n"; break;
- case '\t': a = "\\t"; break;
- case '\'': a = "\\\'"; break;
- case '\"': a = "\\\""; break;
- case '\\': a = "\\\\"; break;
- case ' ': a = " "; break;
- default:
- hex_char_buf[2] = "0123456789abcdef"[*p >> 4];
- hex_char_buf[3] = "0123456789abcdef"[*p & 0xf];
- a = hex_char_buf;
- }
- strcpy(dst, a);
- dst += strlen(a);
- p++;
- }
-}
-
-// taken from kernel
-#define COMMAND_LINE_SIZE 2048
-static char* get_cmdline(pid_t pid)
-{
- char path[sizeof("/proc/%u/cmdline") + sizeof(int)*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);
- int fd = open(path, O_RDONLY);
- if (fd >= 0)
- {
- int len = read(fd, cmdline, sizeof(cmdline) - 1);
- close(fd);
-
- if (len > 0)
- {
- cmdline[len] = '\0';
- char *src = cmdline;
- char *dst = escaped_cmdline;
- while ((src - cmdline) < len)
- {
- dst = append_escaped(dst, src);
- src += strlen(src) + 1;
- }
- }
- }
-
- return xstrdup(escaped_cmdline + 1); /* +1 skips extraneous leading space */
-}
-
-static int daemon_is_ok()
-{
- int fd = open(VAR_RUN_PID_FILE, O_RDONLY);
- if (fd < 0)
- {
- return 0;
- }
-
- char pid[sizeof(pid_t)*3 + 2];
- int len = read(fd, pid, sizeof(pid)-1);
- close(fd);
- if (len <= 0)
- return 0;
-
- pid[len] = '\0';
- *strchrnul(pid, '\n') = '\0';
- /* paranoia: we don't want to check /proc//stat or /proc///stat */
- if (pid[0] == '\0' || pid[0] == '/')
- return 0;
-
- /* TODO: maybe readlink and check that it is "xxx/abrt"? */
- char path[sizeof("/proc/%s/stat") + sizeof(pid)];
- sprintf(path, "/proc/%s/stat", pid);
- struct stat sb;
- if (stat(path, &sb) == -1)
- {
- return 0;
- }
-
- return 1;
-}
-
int main(int argc, char** argv)
{
int fd;
struct stat sb;
const char* program_name = argv[0];
- if (argc < 4)
+ if (argc < 5)
{
- error_msg_and_die("Usage: %s: <dddir> <pid> <signal> <uid>", program_name);
+ error_msg_and_die("Usage: %s: DUMPDIR PID SIGNO UID CORE_SIZE_LIMIT", program_name);
}
openlog("abrt", 0, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
+ errno = 0;
const char* dddir = argv[1];
- pid_t pid = atoi(argv[2]);
+ pid_t pid = xatoi_u(argv[2]);
const char* signal_str = argv[3];
- int signal = atoi(argv[3]);
- uid_t uid = atoi(argv[4]);
-
- if (signal != SIGQUIT
- && signal != SIGILL
- && signal != SIGABRT
- && signal != SIGFPE
- && signal != SIGSEGV
+ 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;
}
- if (pid <= 0 || (int)uid < 0)
- {
- error_msg_and_die("pid '%s' or uid '%s' are bogus", argv[2], argv[4]);
- }
+
char *user_pwd = get_cwd(pid); /* may be NULL on error */
int core_fd = STDIN_FILENO;
@@ -247,6 +121,65 @@ int main(int argc, char** argv)
(int)pid, executable);
}
+ /* 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;
+ }
+
+ 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);
+ }
+
+
char path[PATH_MAX];
/* Check /var/cache/abrt/last-ccpp marker, do not dump repeated crashes
@@ -267,7 +200,12 @@ int main(int argc, char** argv)
{
path[sz] = '\0';
if (strcmp(executable, path) == 0)
- error_msg_and_die("not dumping repeating crash in '%s'", executable);
+ {
+ error_msg("not dumping repeating crash in '%s'", executable);
+ if (setting_MakeCompatCore)
+ goto create_user_core;
+ return 1;
+ }
}
lseek(fd, 0, SEEK_SET);
}
@@ -286,20 +224,20 @@ int main(int argc, char** argv)
*/
snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir);
core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- off_t size = copyfd_eof(STDIN_FILENO, core_fd);
- if (size < 0 || close(core_fd) != 0)
+ 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 %u (%s) to %s (%llu bytes)", (int)pid, executable, path, (long long)size);
+ log("saved core dump of pid %u (%s) to %s (%llu bytes)", (int)pid, executable, path, (long long)core_size);
return 0;
}
char* cmdline = get_cmdline(pid); /* never NULL */
- const char *signame = strsignal(atoi(signal_str));
+ 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);
@@ -325,8 +263,8 @@ int main(int argc, char** argv)
dd.Close();
perror_msg_and_die("can't open '%s'", path);
}
- off_t size = copyfd_eof(STDIN_FILENO, core_fd);
- if (size < 0 || fsync(core_fd) != 0)
+ core_size = copyfd_eof(STDIN_FILENO, core_fd);
+ if (core_size < 0 || fsync(core_fd) != 0)
{
unlink(path);
dd.Delete();
@@ -337,7 +275,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)size);
+ log("saved core dump of pid %u (%s) to %s (%llu bytes)", (int)pid, executable, path, (long long)core_size);
free(executable);
free(cmdline);
path[len] = '\0'; /* path now contains directory name */
@@ -350,64 +288,6 @@ int main(int argc, char** argv)
*/
dd.Close();
- /* 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;
- }
-
- 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)atoi(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);
- }
-
/* rhbz#539551: "abrt going crazy when crashing process is respawned".
* Do we want to protect against or ameliorate this? How? Ideas:
* (1) nice ourself?
@@ -447,7 +327,12 @@ int main(int argc, char** argv)
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);
@@ -520,8 +405,10 @@ int main(int argc, char** argv)
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
- || copyfd_eof(core_fd, usercore_fd) < 0
+ || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0
|| close(usercore_fd) != 0
) {
/* perror first, otherwise unlink may trash errno */
@@ -529,7 +416,16 @@ int main(int argc, char** argv)
unlink(core_basename);
return 1;
}
- log("saved core dump of pid %u to %s/%s", (int)pid, user_pwd, core_basename);
+ 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 %u to %s/%s (%llu bytes)", (int)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 cd17e40..3f79d28 100644
--- a/src/Hooks/abrt-hook-python.cpp
+++ b/src/Hooks/abrt-hook-python.cpp
@@ -34,21 +34,23 @@
static char *pid;
static char *executable;
static char *uuid;
-static char *cmdline;
int main(int argc, char** argv)
{
+ // Error if daemon is not running.
+ if (!daemon_is_ok())
+ error_msg_and_die("Daemon is not running.");
+
// Parse options
static const struct option longopts[] = {
// name , has_arg , flag, val
{ "pid" , required_argument, NULL, 'p' },
{ "executable", required_argument, NULL, 'e' },
{ "uuid" , required_argument, NULL, 'u' },
- { "cmdline" , required_argument, NULL, 'c' },
{ 0 },
};
int opt;
- while ((opt = getopt_long(argc, argv, "p:e:u:c:l:", longopts, NULL)) != -1)
+ while ((opt = getopt_long(argc, argv, "p:e:u:l:", longopts, NULL)) != -1)
{
switch (opt)
{
@@ -61,9 +63,6 @@ int main(int argc, char** argv)
case 'u':
uuid = optarg;
break;
- case 'c':
- cmdline = optarg;
- break;
default:
usage:
error_msg_and_die(
@@ -72,7 +71,6 @@ int main(int argc, char** argv)
" -p,--pid PID PID of process that caused the crash\n"
" -p,--executable PATH absolute path to the program that crashed\n"
" -u,--uuid UUID hash generated from the backtrace\n"
- " -c,--cmdline TEXT command line of the crashed program\n"
);
}
}
@@ -103,8 +101,12 @@ int main(int argc, char** argv)
dd.SaveText(FILENAME_ANALYZER, "Python");
if (executable)
dd.SaveText(FILENAME_EXECUTABLE, executable);
- if (cmdline)
- dd.SaveText("cmdline", cmdline);
+
+ pid_t pidt = xatoi(pid);
+ char *cmdline = get_cmdline(pidt);
+ dd.SaveText("cmdline", cmdline);
+ free(cmdline);
+
if (uuid)
dd.SaveText("uuid", uuid);
diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in
index b5ec35f..a0b0519 100644
--- a/src/Hooks/abrt_exception_handler.py.in
+++ b/src/Hooks/abrt_exception_handler.py.in
@@ -111,7 +111,6 @@ def write_dump(pid, tb_uuid, tb):
command.append("--pid=%s" % pid)
command.append("--executable=%s" % executable)
command.append("--uuid=%s" % tb_uuid)
- command.append("--cmdline=%s" % open("/proc/%s/cmdline" % pid).read().replace('\x00',' '))
helper = subprocess.Popen(command, stdin=subprocess.PIPE)
helper.communicate(tb)
diff --git a/src/Hooks/sitecustomize.py b/src/Hooks/sitecustomize.py
index 8027726..1a01574 100644
--- a/src/Hooks/sitecustomize.py
+++ b/src/Hooks/sitecustomize.py
@@ -5,41 +5,9 @@
# and python interpreter runs it automatically everytime
# some python script is executed.
-def abrt_daemon_ok():
- try:
- #FIXME: make it relocable! this will work only when installed in default path
- #pidfile = open(VAR_RUN_PID_FILE, "r");
- pidfile = open("/var/run/abrt.pid", "r")
- except Exception, ex:
- # log the exception?
- return False
-
- pid = pidfile.readline()
- pidfile.close()
- if not pid:
- return False
-
- try:
- # pid[:-1] strips the trailing '\n'
- cmdline = open("/proc/%s/cmdline" % pid[:-1], "r").readline()
- except Exception, ex:
- # can't read cmdline
- return False
- if not ("abrtd" in cmdline):
- return False
-
- return True
-
-if abrt_daemon_ok():
- # Prevent abrt exception handler from running when the abrtd daemon is
- # not active.
- try:
- from abrt_exception_handler import installExceptionHandler
-
- installExceptionHandler(debug = 1)
- except Exception, e:
- # FIXME: log errors?
- pass
-else:
- #FIXME: log something?
+try:
+ from abrt_exception_handler import installExceptionHandler
+ installExceptionHandler(debug = 1)
+except Exception, e:
+ # FIXME: log errors?
pass