diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | abrt.spec | 1 | ||||
-rw-r--r-- | src/Hooks/Makefile.am | 14 | ||||
-rw-r--r-- | src/Hooks/abrt-hook-python.cpp | 160 |
4 files changed, 176 insertions, 1 deletions
@@ -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/ @@ -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 eec2cd11..3c8aeb94 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 00000000..972f1176 --- /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; +} |