diff options
author | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-10-22 16:08:57 +0200 |
---|---|---|
committer | Jiri Moskovcak <jmoskovc@redhat.com> | 2009-10-22 16:08:57 +0200 |
commit | 67492995a84e88403bfbe5a46627d53dd99e7711 (patch) | |
tree | 57701ad3379abb5530a032fd4c4a2baa41d47a68 | |
parent | 038b9a3473f56dcf80cf5eb053f8cefcc0ef5f01 (diff) | |
parent | 828288e948ccc6c5c1525eaf44bc8cb83960e9f1 (diff) | |
download | abrt-67492995a84e88403bfbe5a46627d53dd99e7711.tar.gz abrt-67492995a84e88403bfbe5a46627d53dd99e7711.tar.xz abrt-67492995a84e88403bfbe5a46627d53dd99e7711.zip |
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | abrt.spec | 1 | ||||
-rw-r--r-- | lib/Plugins/CCpp.cpp | 83 | ||||
-rw-r--r-- | src/CLI/Makefile.am | 2 | ||||
-rw-r--r-- | src/Hooks/Makefile.am | 18 | ||||
-rw-r--r-- | src/Hooks/abrt-pyhook-helper.cpp | 138 | ||||
-rw-r--r-- | src/Hooks/abrt_exception_handler.py.in | 53 | ||||
-rw-r--r-- | src/Hooks/sitecustomize.py | 12 |
8 files changed, 264 insertions, 44 deletions
@@ -45,4 +45,5 @@ src/Daemon/abrtd src/Hooks/abrt_exception_handler.py src/Hooks/dumpoops src/Hooks/hookCCpp +src/Hooks/abrt-pyhook-helper stamp-h1 @@ -346,6 +346,7 @@ fi %files addon-python %defattr(-,root,root,-) +%{_bindir}/%{name}-pyhook-helper %config(noreplace) %{_sysconfdir}/%{name}/pyhook.conf %{python_sitearch}/ABRTUtils.so %{_libdir}/%{name}/libPython.so* diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 0e0eb3b3..f79877e6 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -156,6 +156,89 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput) return 0; } +enum LineRating +{ + /* RATING -- EXAMPLE */ + MissingEverything = 0, // #0 0x0000dead in ?? () + MissingFunction = 1, // #0 0x0000dead in ?? () from /usr/lib/libfoobar.so.4 + MissingLibrary = 2, // #0 0x0000dead in foobar() + MissingSourceFile = 3, // #0 0x0000dead in FooBar::FooBar () from /usr/lib/libfoobar.so.4 + Good = 4, // #0 0x0000dead in FooBar::crash (this=0x0) at /home/user/foobar.cpp:204 + InvalidRating = -1 // (dummy invalid value) +}; + +static const LineRating BestRating = Good; + +LineRating rate_line(std::string line) +{ + bool function = false; + bool library = false; + bool source_file = false; + +#define FOUND(x) (line.find(x) != std::string::npos) + if (FOUND(" in ") && !FOUND(" in ??")) + function = true; + + if (FOUND(" from ")) + library = true; + + if(FOUND(" at ")) + source_file = true; +#undef FOUND + + /* see the "enum LineRating" comments for possible combinations */ + if (function && source_file) + return Good; + if (function && library) + return MissingSourceFile; + if (function) + return MissingLibrary; + if (library) + return MissingFunction; + + return MissingEverything; +} + +/* returns number of "stars" to show*/ +int rate_backtrace(std::string backtrace) +{ + int l = backtrace.length(); + int i; + std::string s = ""; + int multiplier = 0; + int rating = 0; + int best_possible_rating = 0; + + /*we get the lines from the end, b/c of the rating multiplier + which gives weight to the first lines*/ + for (i=l-1; i>=0; i--) + { + if (backtrace[i] == '#') /*this divides frames from each other*/ + { + multiplier++; + rating += rate_line(s) * multiplier; + best_possible_rating += BestRating * multiplier; + + s = ""; /*starting new line*/ + } else + { + s=backtrace[i]+s; + } + } + + /*returning number of "stars" to show*/ + if (rating >= best_possible_rating*0.8) + return 4; + if (rating >= best_possible_rating*0.6) + return 3; + if (rating >= best_possible_rating*0.4) + return 2; + if (rating >= best_possible_rating*0.2) + return 1; + + return 0; +} + static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktrace) { update_client(_("Getting backtrace...")); diff --git a/src/CLI/Makefile.am b/src/CLI/Makefile.am index 7b10bfb8..dbeb1c38 100644 --- a/src/CLI/Makefile.am +++ b/src/CLI/Makefile.am @@ -27,6 +27,6 @@ man_MANS = abrt-cli.1 EXTRA_DIST = $(man_MANS) completiondir = $(sysconfdir)/bash_completion.d -completion_DATA = abrt-cli.bash +dist_completion_DATA = abrt-cli.bash DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am index be1b1a2f..4eb25e2d 100644 --- a/src/Hooks/Makefile.am +++ b/src/Hooks/Makefile.am @@ -1,5 +1,5 @@ libexec_PROGRAMS = hookCCpp -bin_PROGRAMS = dumpoops +bin_PROGRAMS = dumpoops abrt-pyhook-helper # CCpp hookCCpp_SOURCES = \ @@ -29,6 +29,18 @@ dumpoops_CPPFLAGS = \ dumpoops_LDADD = \ ../../lib/Utils/libABRTUtils.la +# abrt-pyhook-helper +abrt_pyhook_helper_SOURCES = \ + abrt-pyhook-helper.cpp +abrt_pyhook_helper_CPPFLAGS = \ + -I$(srcdir)/../../inc \ + -I$(srcdir)/../../lib/Utils \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + -D_GNU_SOURCE +abrt_pyhook_helper_LDADD = \ + ../../lib/Utils/libABRTUtils.la + man_MANS = pyhook.conf.5 python_PYTHON = sitecustomize.py abrt_exception_handler.py @@ -45,3 +57,7 @@ abrt_exception_handler.py: # RPM fix: we need to regenerate abrt_exception_handler.py, because it has the default ddir install-data-local: sed s,@DEBUG_DUMP_DIR@,$(DEBUG_DUMPS_DIR),g abrt_exception_handler.py.in > abrt_exception_handler.py + +install-data-hook: + chmod u+s,g+s $(DESTDIR)$(bindir)/abrt-pyhook-helper + diff --git a/src/Hooks/abrt-pyhook-helper.cpp b/src/Hooks/abrt-pyhook-helper.cpp new file mode 100644 index 00000000..4ac6ada6 --- /dev/null +++ b/src/Hooks/abrt-pyhook-helper.cpp @@ -0,0 +1,138 @@ +/* + python-hook-writer.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 <argp.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "DebugDump.h" +#if HAVE_CONFIG_H +#include <config.h> +#endif + +const char *argp_program_version = "abrt-pyhook-helper " VERSION; +const char *argp_program_bug_address = "<crash-catcher@lists.fedorahosted.org>"; + +static char doc[] = "abrt-pyhook-helper -- stores crash data to abrt shared directory"; + +static struct argp_option options[] = { + {"pid" , 'p', "PID" , 0, "PID of process that caused the crash" }, + {"executable", 'e', "PATH" , 0, "absolute path to the program that crashed" }, + {"uuid" , 'u', "UUID" , 0, "hash generated from the backtrace"}, + {"cmdline" , 'c', "TEXT" , 0, "command line of the crashed program"}, + {"loginuid" , 'l', "UID" , 0, "login UID"}, + { 0 } +}; + +struct arguments +{ + char *pid; + char *executable; + char *uuid; + char *cmdline; + char *loginuid; +}; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = (struct arguments*)state->input; + + switch (key) + { + case 'p': arguments->pid = arg; break; + case 'e': arguments->executable = arg; break; + case 'u': arguments->uuid = arg; break; + case 'c': arguments->cmdline = arg; break; + case 'l': arguments->loginuid = arg; break; + + case ARGP_KEY_ARG: + argp_usage(state); + exit(1); + break; + + case ARGP_KEY_END: + if (!arguments->pid) + { + argp_usage(state); + exit(1); + } + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +/* Our argp parser. */ +static struct argp argp = { options, parse_opt, 0, doc }; + +int main(int argc, char** argv) +{ + struct arguments arguments; + argp_parse (&argp, argc, argv, 0, 0, &arguments); + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/pyhook-%ld-%s", DEBUG_DUMPS_DIR, + (long)time(NULL), arguments.pid); + + CDebugDump dd; + dd.Create(path, geteuid()); + dd.SaveText(FILENAME_ANALYZER, "Python"); + if (arguments.executable) + dd.SaveText(FILENAME_EXECUTABLE, arguments.executable); + if (arguments.cmdline) + dd.SaveText("cmdline", arguments.cmdline); + if (arguments.uuid) + dd.SaveText("uuid", arguments.uuid); + if (arguments.loginuid) + dd.SaveText("uid", arguments.loginuid); + + // Read the backtrace from stdin. + int c; + int capacity = 1024; + char *bt = (char*)malloc(capacity); + char *btptr = bt; + while ((c = getchar()) != EOF) + { + if (c >= 0 && c <= 255) + *btptr++ = (char)c; + if (btptr - bt >= capacity - 1) + { + capacity *= 2; + bt = (char*)realloc(bt, capacity); + if (!bt) + { + printf("Error while allocating memory for backtrace."); + return 1; + } + } + } + *btptr = '\0'; + + dd.SaveText("backtrace", bt); + free(bt); + dd.Close(); + + return 0; +} diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in index 8ac7aa23..362aaf24 100644 --- a/src/Hooks/abrt_exception_handler.py.in +++ b/src/Hooks/abrt_exception_handler.py.in @@ -45,10 +45,10 @@ def exception_function(): import sys import os import syslog +import subprocess # abrt lib for saving debugdumps import ABRTUtils - __DUMPHASH = {} # FIXME: do length limits on obj dumps. def __dump_class(instance, fd, level=0): @@ -105,45 +105,20 @@ def __dump_class(instance, fd, level=0): fd.write("%s%s: %s\n" % (pad, key, value)) def write_dump(pid, tb_uuid, tb): - import time - ttime = int(time.time()) - # localstatedir - dir_name = "@DEBUG_DUMP_DIR@/pyhook-%s-%s" % (ttime, pid) - dd = ABRTUtils.CDebugDump() - try: - #os.mkdir(dir_name) - dd.Create(dir_name, os.getuid()) - except Exception, e: - syslog.syslog("abrt: Cannot create dir %s %s" % (dir_name, e)) - return - # save executable - fexecutable = open("%s/executable" % dir_name, "w") + executable = "Exception raised from python shell" if sys.argv[0]: - fexecutable.write(os.path.abspath(sys.argv[0])) - else: - fexecutable.write("Exception raised from python shell") - fexecutable.close() - # save coredump - coredump = open("%s/backtrace" % dir_name, "w") - coredump.write(tb) - coredump.close() - # save uuid - uuid = open("%s/uuid" % dir_name, "w") - uuid.write(tb_uuid) - uuid.close() - # save cmdline - cmdline = open("%s/cmdline" % dir_name, "w") - cmdline.write(open("/proc/%s/cmdline" % pid).read().replace('\x00',' ')) - cmdline.close() - # save uid - uid = open("%s/uid" % dir_name, "w") - uid.write(open("/proc/%s/loginuid" % pid).readlines()[0]) - uid.close() - # save analyzer - analyzer = open("%s/analyzer" % dir_name, "w") - analyzer.write("Python") - analyzer.close() - dd.Close() + executable = os.path.abspath(sys.argv[0]) + + command = ["abrt-pyhook-helper"] + 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',' ')) + command.append("--loginuid=%s" % open("/proc/%s/loginuid" % pid).readlines()[0]) + + helper = subprocess.Popen(command, stdin=subprocess.PIPE) + helper.communicate(tb) + helper.wait() def __dump_exception(out, text, tracebk): 'write a traceback to "out"' diff --git a/src/Hooks/sitecustomize.py b/src/Hooks/sitecustomize.py index 56c6669b..32a3747b 100644 --- a/src/Hooks/sitecustomize.py +++ b/src/Hooks/sitecustomize.py @@ -1,14 +1,16 @@ +# ABRT crash hook +# # This special script is placed in # /usr/local/lib/pythonNNN/site-packages/sitecustomize.py # and python interpreter runs it automatically everytime -# some python script is executed +# some python script is executed. config = None conf = {} try: config = open("/etc/abrt/pyhook.conf","r") except: - #silently ignore if file doesn't exist + # Silently ignore if file doesn't exist. pass try: @@ -20,10 +22,14 @@ try: line = config.readline().lower().replace(' ','').strip('\n').split('=') conf[line[0]] = line[1] except: - # ignore silently everything, because we don't want to bother user if this hook doesn't work + # Ignore silently everything, because we don't want to bother user + # if this hook doesn't work. pass if conf.has_key("enabled"): + # Prevent abrt exception handler from running when the abrtd daemon is + # not active. + # abrtd sets the value to "no" when deactivated and vice versa. if conf["enabled"] == "yes": try: from abrt_exception_handler import * |