summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--abrt.spec1
-rw-r--r--src/Hooks/Makefile.am14
-rw-r--r--src/Hooks/abrt-hook-python.cpp160
4 files changed, 176 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 9220ec3..add9490 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,11 +51,13 @@ src/CLI/abrt-cli
src/utils/abrt-backtrace
lib/Utils/backtrace_parser.c
lib/Utils/backtrace_parser.output
+src/Backtrace/*.bt
src/Daemon/abrtd
src/Gui/abrt.desktop
src/Hooks/abrt_exception_handler.py
src/Hooks/dumpoops
src/Hooks/abrt-hook-ccpp
+src/Hooks/abrt-hook-python
scripts/abrt-rate-backtrace
stamp-h1
x86_64/
diff --git a/abrt.spec b/abrt.spec
index 035649b..a30dd0d 100644
--- a/abrt.spec
+++ b/abrt.spec
@@ -440,6 +440,7 @@ 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*
%{python_site}/abrt.pth
diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am
index eec2cd1..3c8aeb9 100644
--- a/src/Hooks/Makefile.am
+++ b/src/Hooks/Makefile.am
@@ -1,4 +1,4 @@
-libexec_PROGRAMS = abrt-hook-ccpp
+libexec_PROGRAMS = abrt-hook-ccpp abrt-hook-python
bin_PROGRAMS = dumpoops
# abrt-hook-ccpp
@@ -30,6 +30,18 @@ dumpoops_LDADD = \
../../lib/Utils/libABRTUtils.la \
../../lib/Utils/libABRTdUtils.la
+# abrt-hook-python
+abrt_hook_python_SOURCES = abrt-hook-python.cpp
+abrt_hook_python_CPPFLAGS = \
+ -I$(srcdir)/../../inc \
+ -I$(srcdir)/../../lib/Utils \
+ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+ -DCONF_DIR=\"$(CONF_DIR)\" \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -D_GNU_SOURCE
+abrt_hook_python_LDADD = \
+ ../../lib/Utils/libABRTUtils.la
+
python_PYTHON = abrt.pth abrt_exception_handler.py
EXTRA_DIST = abrt_exception_handler.py.in $(man_MANS)
diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp
new file mode 100644
index 0000000..972f117
--- /dev/null
+++ b/src/Hooks/abrt-hook-python.cpp
@@ -0,0 +1,160 @@
+/*
+ abrt-hook-python.cpp - writes data to the /var/cache/abrt directory
+ with SUID bit
+
+ 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 <getopt.h>
+#include <syslog.h>
+// 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"
+#include "CrashTypes.h"
+#include "ABRTException.h"
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define MAX_BT_SIZE (1024*1024)
+#define MAX_BT_SIZE_STR "1 MB"
+
+static char *pid;
+static char *executable;
+
+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
+ { "pid" , required_argument, NULL, 'p' },
+ { "executable", required_argument, NULL, 'e' },
+ { 0 },
+ };
+ int opt;
+ while ((opt = getopt_long(argc, argv, "p:e:u:l:", longopts, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 'p':
+ pid = optarg;
+ break;
+ case 'e':
+ executable = optarg;
+ break;
+ default:
+ usage:
+ error_msg_and_die(
+ "Usage: abrt-hook-python [OPTIONS] <BACKTRACE\n"
+ "\nOptions:\n"
+ " -p,--pid PID PID of process that caused the crash\n"
+ " -p,--executable PATH absolute path to the program that crashed\n"
+ );
+ }
+ }
+ if (!pid || !executable)
+ goto usage;
+ if (strlen(executable) > PATH_MAX || !printable_str(executable))
+ goto usage;
+ // pid string is sanitized later by xatou()
+
+ 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);
+ if (setting_MaxCrashReportsSize > 0)
+ {
+ check_free_space(setting_MaxCrashReportsSize);
+ }
+
+ // Read the backtrace from stdin
+ char *bt = (char*)xmalloc(MAX_BT_SIZE);
+ ssize_t len = full_read(STDIN_FILENO, bt, MAX_BT_SIZE-1);
+ if (len < 0)
+ {
+ 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);
+ }
+
+ // This also checks that pid is a valid numeric string
+ char *cmdline = get_cmdline(xatou(pid)); // never NULL
+
+ // Create directory with the debug dump
+ char path[PATH_MAX];
+ unsigned path_len = snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s.new",
+ (long)time(NULL), pid);
+ if (path_len >= sizeof(path))
+ exit(1);
+ CDebugDump dd;
+ try {
+ dd.Create(path, getuid());
+ } catch (CABRTException &e) {
+ dd.Delete();
+ dd.Close();
+ error_msg_and_die("error while creating crash dump %s: %s", path, e.what());
+ }
+
+ dd.SaveText(FILENAME_ANALYZER, "Python");
+ dd.SaveText(FILENAME_EXECUTABLE, executable);
+ dd.SaveText(FILENAME_BACKTRACE, bt);
+ // python handler puts a short(er) crash descr in 1st line. Example:
+ // "CCMainWindow.py:1:<module>:ZeroDivisionError: integer division or modulo by zero"
+ strchrnul(bt, '\n')[0] = '\0';
+ dd.SaveText(FILENAME_REASON, bt);
+ free(bt);
+ dd.SaveText(FILENAME_CMDLINE, cmdline);
+ free(cmdline);
+ char uid[sizeof(long) * 3 + 2];
+ sprintf(uid, "%lu", (long)getuid());
+ dd.SaveText(CD_UID, uid);
+
+ dd.Close();
+
+ char *newpath = xstrndup(path, path_len - (sizeof(".new")-1));
+ if (rename(path, newpath) != 0)
+ strcpy(path, newpath);
+ free(newpath);
+
+ log("saved python crash dump of pid %s to %s", pid, path);
+
+ if (setting_MaxCrashReportsSize > 0)
+ {
+ trim_debug_dumps(setting_MaxCrashReportsSize, path);
+ }
+
+ return 0;
+}