|
Packit |
8ea169 |
/*
|
|
Packit |
8ea169 |
Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com)
|
|
Packit |
8ea169 |
Copyright (C) 2009 RedHat inc.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
8ea169 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
8ea169 |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
8ea169 |
(at your option) any later version.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
8ea169 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8ea169 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8ea169 |
GNU General Public License for more details.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
You should have received a copy of the GNU General Public License along
|
|
Packit |
8ea169 |
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
8ea169 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
#include <fnmatch.h>
|
|
Packit |
8ea169 |
#include <glib.h>
|
|
Packit |
8ea169 |
#include "libabrt.h"
|
|
Packit |
8ea169 |
#include "rpm.h"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#define GPG_CONF "gpg_keys.conf"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/**
|
|
Packit |
8ea169 |
"python3.4, python3.5, python3.6, python3.7, perl, perl5.16.2"
|
|
Packit |
8ea169 |
* The regexes should cover interpreters with basename:
|
|
Packit |
8ea169 |
* Python:
|
|
Packit |
8ea169 |
* python
|
|
Packit |
8ea169 |
* python2
|
|
Packit |
8ea169 |
* python3
|
|
Packit |
8ea169 |
* python2.7
|
|
Packit |
8ea169 |
* python3.8
|
|
Packit |
8ea169 |
* platform-python
|
|
Packit |
8ea169 |
* platform-python3
|
|
Packit |
8ea169 |
* platform-python3.8
|
|
Packit |
8ea169 |
*
|
|
Packit |
8ea169 |
* Perl:
|
|
Packit |
8ea169 |
* perl
|
|
Packit |
8ea169 |
* perl5.30.1
|
|
Packit |
8ea169 |
*
|
|
Packit |
8ea169 |
* PHP:
|
|
Packit |
8ea169 |
* php
|
|
Packit |
8ea169 |
* php-cgi
|
|
Packit |
8ea169 |
*
|
|
Packit |
8ea169 |
* R:
|
|
Packit |
8ea169 |
* R
|
|
Packit |
8ea169 |
*
|
|
Packit |
8ea169 |
* tcl:
|
|
Packit |
8ea169 |
* tclsh
|
|
Packit |
8ea169 |
* tclsh8.6
|
|
Packit |
8ea169 |
**/
|
|
Packit |
8ea169 |
#define DEFAULT_INTERPRETERS_REGEX \
|
|
Packit |
8ea169 |
"^(perl ([[:digit:]][.][[:digit:]]+[.][[:digit:]])? |" \
|
|
Packit |
8ea169 |
"php (-cgi)? |" \
|
|
Packit |
8ea169 |
"(platform-)? python ([[:digit:]]([.][[:digit:]])?)? |" \
|
|
Packit |
8ea169 |
"R |" \
|
|
Packit |
8ea169 |
"tclsh ([[:digit:]][.][[:digit:]])?)$"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static bool settings_bOpenGPGCheck = false;
|
|
Packit |
8ea169 |
static GList *settings_setOpenGPGPublicKeys = NULL;
|
|
Packit |
8ea169 |
static GList *settings_setBlackListedPkgs = NULL;
|
|
Packit |
8ea169 |
static GList *settings_setBlackListedPaths = NULL;
|
|
Packit |
8ea169 |
static bool settings_bProcessUnpackaged = false;
|
|
Packit |
8ea169 |
static GList *settings_Interpreters = NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void ParseCommon(map_string_t *settings, const char *conf_filename)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
const char *value;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
value = get_map_string_item_or_NULL(settings, "OpenGPGCheck");
|
|
Packit |
8ea169 |
if (value)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
settings_bOpenGPGCheck = string_to_bool(value);
|
|
Packit |
8ea169 |
remove_map_string_item(settings, "OpenGPGCheck");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
value = get_map_string_item_or_NULL(settings, "BlackList");
|
|
Packit |
8ea169 |
if (value)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
settings_setBlackListedPkgs = parse_list(value);
|
|
Packit |
8ea169 |
remove_map_string_item(settings, "BlackList");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
value = get_map_string_item_or_NULL(settings, "BlackListedPaths");
|
|
Packit |
8ea169 |
if (value)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
settings_setBlackListedPaths = parse_list(value);
|
|
Packit |
8ea169 |
remove_map_string_item(settings, "BlackListedPaths");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
value = get_map_string_item_or_NULL(settings, "ProcessUnpackaged");
|
|
Packit |
8ea169 |
if (value)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
settings_bProcessUnpackaged = string_to_bool(value);
|
|
Packit |
8ea169 |
remove_map_string_item(settings, "ProcessUnpackaged");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
value = get_map_string_item_or_NULL(settings, "Interpreters");
|
|
Packit |
8ea169 |
if (value)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
settings_Interpreters = parse_list(value);
|
|
Packit |
8ea169 |
remove_map_string_item(settings, "Interpreters");
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
map_string_iter_t iter;
|
|
Packit |
8ea169 |
const char *name;
|
|
Packit |
8ea169 |
/*char *value; - already declared */
|
|
Packit |
8ea169 |
init_map_string_iter(&iter, settings);
|
|
Packit |
8ea169 |
while (next_map_string_iter(&iter, &name, &value))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("Unrecognized variable '%s' in '%s'", name, conf_filename);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static void load_gpg_keys(void)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
map_string_t *settings = new_map_string();
|
|
Packit |
8ea169 |
if (!load_abrt_conf_file(GPG_CONF, settings))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
error_msg("Can't load '%s'", GPG_CONF);
|
|
Packit |
8ea169 |
return;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const char *gpg_keys_dir = get_map_string_item_or_NULL(settings, "GPGKeysDir");
|
|
Packit |
8ea169 |
if (gpg_keys_dir != NULL && strcmp(gpg_keys_dir, "") != 0)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_debug("Reading gpg keys from '%s'", gpg_keys_dir);
|
|
Packit |
8ea169 |
GHashTable *done_set = g_hash_table_new(g_str_hash, g_str_equal);
|
|
Packit |
8ea169 |
GList *gpg_files = get_file_list(gpg_keys_dir, NULL /* we don't care about the file ext */);
|
|
Packit |
8ea169 |
for (GList *iter = gpg_files; iter; iter = g_list_next(iter))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
const char *key_path = fo_get_fullpath((file_obj_t *)iter->data);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (g_hash_table_contains(done_set, key_path))
|
|
Packit |
8ea169 |
continue;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_hash_table_insert(done_set, (gpointer)key_path, NULL);
|
|
Packit |
8ea169 |
log_debug("Loading gpg key '%s'", key_path);
|
|
Packit |
8ea169 |
settings_setOpenGPGPublicKeys = g_list_append(settings_setOpenGPGPublicKeys, xstrdup(key_path));
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
g_list_free_full(gpg_files, (GDestroyNotify)free_file_obj);
|
|
Packit |
8ea169 |
g_hash_table_destroy(done_set);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static int load_conf(const char *conf_filename)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
map_string_t *settings = new_map_string();
|
|
Packit |
8ea169 |
if (conf_filename != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (!load_conf_file(conf_filename, settings, false))
|
|
Packit |
8ea169 |
error_msg("Can't open '%s'", conf_filename);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
conf_filename = "abrt-action-save-package-data.conf";
|
|
Packit |
8ea169 |
if (!load_abrt_conf_file(conf_filename, settings))
|
|
Packit |
8ea169 |
error_msg("Can't load '%s'", conf_filename);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
ParseCommon(settings, conf_filename);
|
|
Packit |
8ea169 |
free_map_string(settings);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
load_gpg_keys();
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return 0;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/**
|
|
Packit |
8ea169 |
* Returns the first full path argument in the command line or NULL.
|
|
Packit |
8ea169 |
* Skips options (params of the form "-XXX").
|
|
Packit |
8ea169 |
* Returns malloc'ed string.
|
|
Packit |
8ea169 |
* NB: the cmdline is delimited by (single, not multiple) spaces, not tabs!
|
|
Packit |
8ea169 |
* "abc def\t123" means there are two params: "abc", "def\t123".
|
|
Packit |
8ea169 |
* "abc def" means there are three params: "abc", "", "def".
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
static char *get_argv1_if_full_path(const char* cmdline)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
const char *argv1 = strchr(cmdline, ' ');
|
|
Packit |
8ea169 |
while (argv1 != NULL)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
/* we found space in cmdline, so it might contain
|
|
Packit |
8ea169 |
* path to some script like:
|
|
Packit |
8ea169 |
* /usr/bin/python [-XXX] /usr/bin/system-control-network
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
argv1++; /* skip the space */
|
|
Packit |
8ea169 |
if (*argv1 != '-')
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
/* looks like -XXX in "perl -XXX /usr/bin/script.pl", skipping */
|
|
Packit |
8ea169 |
argv1 = strchr(argv1, ' ');
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* if the string following the space doesn't start
|
|
Packit |
8ea169 |
* with '/', it is not a full path to script
|
|
Packit |
8ea169 |
* and we can't use it to determine the package name
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
if (argv1 == NULL || *argv1 != '/')
|
|
Packit |
8ea169 |
return NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* good, it has "/foo/bar" form, return it */
|
|
Packit |
8ea169 |
int len = strchrnul(argv1, ' ') - argv1;
|
|
Packit |
8ea169 |
return xstrndup(argv1, len);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static bool is_path_blacklisted(const char *path)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
GList *li;
|
|
Packit |
8ea169 |
for (li = settings_setBlackListedPaths; li != NULL; li = g_list_next(li))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (fnmatch((char*)li->data, path, /*flags:*/ 0) == 0)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
return true;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
return false;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static struct pkg_envra *get_script_name(const char *cmdline, char **executable, const char *chroot)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
// TODO: we don't verify that python executable is not modified
|
|
Packit |
8ea169 |
// or that python package is properly signed
|
|
Packit |
8ea169 |
// (see CheckFingerprint/CheckHash below)
|
|
Packit |
8ea169 |
/* Try to find package for the script by looking at argv[1].
|
|
Packit |
8ea169 |
* This will work only if the cmdline contains the whole path.
|
|
Packit |
8ea169 |
* Example: python /usr/bin/system-control-network
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
struct pkg_envra *script_pkg = NULL;
|
|
Packit |
8ea169 |
char *script_name = get_argv1_if_full_path(cmdline);
|
|
Packit |
8ea169 |
if (script_name)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
script_pkg = rpm_get_package_nvr(script_name, chroot);
|
|
Packit |
8ea169 |
if (script_pkg)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
/* There is a well-formed script name in argv[1],
|
|
Packit |
8ea169 |
* and it does belong to some package.
|
|
Packit |
8ea169 |
* Replace executable
|
|
Packit |
8ea169 |
* with data pertaining to the script.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
*executable = script_name;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return script_pkg;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
static int SavePackageDescriptionToDebugDump(const char *dump_dir_name, const char *chroot)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
|
|
Packit |
8ea169 |
if (!dd)
|
|
Packit |
8ea169 |
return 1;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
char *type = dd_load_text(dd, FILENAME_TYPE);
|
|
Packit |
8ea169 |
bool kernel_oops = !strcmp(type, "Kerneloops") || !strcmp(type, "vmcore");
|
|
Packit |
8ea169 |
free(type);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
char *cmdline = NULL;
|
|
Packit |
8ea169 |
char *executable = NULL;
|
|
Packit |
8ea169 |
char *rootdir = NULL;
|
|
Packit |
8ea169 |
char *package_short_name = NULL;
|
|
Packit |
8ea169 |
char *fingerprint = NULL;
|
|
Packit |
8ea169 |
struct pkg_envra *pkg_name = NULL;
|
|
Packit |
8ea169 |
char *component = NULL;
|
|
Packit |
8ea169 |
char *kernel = NULL;
|
|
Packit |
8ea169 |
int error = 1;
|
|
Packit |
8ea169 |
/* note: "goto ret" statements below free all the above variables,
|
|
Packit |
8ea169 |
* but they don't dd_close(dd) */
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (kernel_oops)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
kernel = dd_load_text(dd, FILENAME_KERNEL);
|
|
Packit |
8ea169 |
if (!kernel)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("File 'kernel' containing kernel version not "
|
|
Packit |
8ea169 |
"found in current directory");
|
|
Packit |
8ea169 |
goto ret;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
/* Trim trailing white-spaces. */
|
|
Packit |
8ea169 |
strchrnul(kernel, ' ')[0] = '\0';
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_info("Looking for kernel package");
|
|
Packit |
8ea169 |
executable = xasprintf("/boot/vmlinuz-%s", kernel);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
cmdline = dd_load_text_ext(dd, FILENAME_CMDLINE, DD_FAIL_QUIETLY_ENOENT);
|
|
Packit |
8ea169 |
executable = dd_load_text(dd, FILENAME_EXECUTABLE);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Do not implicitly query rpm database in process's root dir, if
|
|
Packit |
8ea169 |
* ExploreChroots is disabled. */
|
|
Packit |
8ea169 |
if (g_settings_explorechroots && chroot == NULL)
|
|
Packit |
8ea169 |
chroot = rootdir = dd_load_text_ext(dd, FILENAME_ROOTDIR,
|
|
Packit |
8ea169 |
DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Close dd while we query package database. It can take some time,
|
|
Packit |
8ea169 |
* don't want to keep dd locked longer than necessary */
|
|
Packit |
8ea169 |
dd_close(dd);
|
|
Packit |
8ea169 |
dd = NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* The check for kernel_oops is there because it could be an unexpected
|
|
Packit |
8ea169 |
* behaviour. If one wants to ignore kernel oops, she/he should disable
|
|
Packit |
8ea169 |
* the corresponding services. */
|
|
Packit |
8ea169 |
if (!kernel_oops && is_path_blacklisted(executable))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Blacklisted executable '%s'", executable);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
pkg_name = rpm_get_package_nvr(executable, chroot);
|
|
Packit |
8ea169 |
if (!pkg_name)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
if (settings_bProcessUnpackaged)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_info("Crash in unpackaged executable '%s', "
|
|
Packit |
8ea169 |
"proceeding without packaging information", executable);
|
|
Packit |
8ea169 |
goto ret0; /* no error */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
if (kernel_oops)
|
|
Packit |
8ea169 |
log_warning("Can't find kernel package corresponding to '%s'", kernel);
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
log_warning("Executable '%s' doesn't belong to any package"
|
|
Packit |
8ea169 |
" and ProcessUnpackaged is set to 'no'", executable);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (kernel_oops)
|
|
Packit |
8ea169 |
goto skip_interpreter;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Check well-known interpreter names */
|
|
Packit |
8ea169 |
const char *basename = strrchr(executable, '/');
|
|
Packit |
8ea169 |
if (basename)
|
|
Packit |
8ea169 |
basename++;
|
|
Packit |
8ea169 |
else
|
|
Packit |
8ea169 |
basename = executable;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* if basename is known interpreter, we want to blame the running script
|
|
Packit |
8ea169 |
* not the interpreter
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
if (g_regex_match_simple(DEFAULT_INTERPRETERS_REGEX, basename, G_REGEX_EXTENDED, /*MatchFlags*/0) ||
|
|
Packit |
8ea169 |
g_list_find_custom(settings_Interpreters, basename, (GCompareFunc)g_strcmp0))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
struct pkg_envra *script_pkg = get_script_name(cmdline, &executable, chroot);
|
|
Packit |
8ea169 |
/* executable may have changed, check it again */
|
|
Packit |
8ea169 |
if (is_path_blacklisted(executable))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Blacklisted executable '%s'", executable);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
if (!script_pkg)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
/* Script name is not absolute, or it doesn't
|
|
Packit |
8ea169 |
* belong to any installed package.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
if (!settings_bProcessUnpackaged)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Interpreter crashed, but no packaged script detected: '%s'", cmdline);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Unpackaged script, but the settings says we want to keep it.
|
|
Packit |
8ea169 |
* BZ plugin wont allow to report this anyway, because component
|
|
Packit |
8ea169 |
* is missing, so there is no reason to mark it as not_reportable.
|
|
Packit |
8ea169 |
* Someone might want to use abrt to report it using ftp.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
goto ret0;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
free_pkg_envra(pkg_name);
|
|
Packit |
8ea169 |
pkg_name = script_pkg;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
skip_interpreter:
|
|
Packit |
8ea169 |
package_short_name = xasprintf("%s", pkg_name->p_name);
|
|
Packit |
8ea169 |
log_info("Package:'%s' short:'%s'", pkg_name->p_nvr, package_short_name);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* The check for kernel_oops is there because it could be an unexpected
|
|
Packit |
8ea169 |
* behaviour. If one wants to ignore kernel oops, she/he should disable
|
|
Packit |
8ea169 |
* the corresponding services. */
|
|
Packit |
8ea169 |
if (!kernel_oops && g_list_find_custom(settings_setBlackListedPkgs, package_short_name, (GCompareFunc)g_strcmp0))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Blacklisted package '%s'", package_short_name);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
fingerprint = rpm_get_fingerprint(package_short_name);
|
|
Packit |
8ea169 |
if (!(fingerprint != NULL && rpm_fingerprint_is_imported(fingerprint))
|
|
Packit |
8ea169 |
&& settings_bOpenGPGCheck)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_warning("Package '%s' isn't signed with proper key", package_short_name);
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
/* We used to also check the integrity of the executable here:
|
|
Packit |
8ea169 |
* if (!CheckHash(package_short_name.c_str(), executable)) BOOM();
|
|
Packit |
8ea169 |
* Checking the MD5 sum requires to run prelink to "un-prelink" the
|
|
Packit |
8ea169 |
* binaries - this is considered potential security risk so we don't
|
|
Packit |
8ea169 |
* do it now, until we find some non-intrusive way.
|
|
Packit |
8ea169 |
*/
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
component = rpm_get_component(executable, chroot);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
|
|
Packit |
8ea169 |
if (!dd)
|
|
Packit |
8ea169 |
goto ret; /* return 1 (failure) */
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (pkg_name)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PACKAGE, pkg_name->p_nvr);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_EPOCH, pkg_name->p_epoch);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_NAME, pkg_name->p_name);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_VERSION, pkg_name->p_version);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_RELEASE, pkg_name->p_release);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_ARCH, pkg_name->p_arch);
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_VENDOR, pkg_name->p_vendor);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (fingerprint)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
/* 16 character + 3 spaces + 1 '\0' + 2 Bytes for errors :) */
|
|
Packit |
8ea169 |
char key_fingerprint[22] = {0};
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* The condition is just a defense against errors */
|
|
Packit |
8ea169 |
for (size_t i = 0, j = 0; j < sizeof(key_fingerprint) - 2; )
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
key_fingerprint[j++] = toupper(fingerprint[i++]);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (fingerprint[i] == '\0')
|
|
Packit |
8ea169 |
break;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (!(i & (0x3)))
|
|
Packit |
8ea169 |
key_fingerprint[j++] = ' ';
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_PKG_FINGERPRINT, key_fingerprint);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if (component)
|
|
Packit |
8ea169 |
dd_save_text(dd, FILENAME_COMPONENT, component);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
ret0:
|
|
Packit |
8ea169 |
error = 0;
|
|
Packit |
8ea169 |
ret:
|
|
Packit |
8ea169 |
if (dd)
|
|
Packit |
8ea169 |
dd_close(dd);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
free(cmdline);
|
|
Packit |
8ea169 |
free(executable);
|
|
Packit |
8ea169 |
free(rootdir);
|
|
Packit |
8ea169 |
free(package_short_name);
|
|
Packit |
8ea169 |
free_pkg_envra(pkg_name);
|
|
Packit |
8ea169 |
free(component);
|
|
Packit |
8ea169 |
free(fingerprint);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return error;
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int main(int argc, char **argv)
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
/* I18n */
|
|
Packit |
8ea169 |
setlocale(LC_ALL, "");
|
|
Packit |
8ea169 |
#if ENABLE_NLS
|
|
Packit |
8ea169 |
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
Packit |
8ea169 |
textdomain(PACKAGE);
|
|
Packit |
8ea169 |
#endif
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
abrt_init(argv);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
const char *dump_dir_name = ".";
|
|
Packit |
8ea169 |
const char *conf_filename = NULL;
|
|
Packit |
8ea169 |
const char *chroot = NULL;
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Can't keep these strings/structs static: _() doesn't support that */
|
|
Packit |
8ea169 |
const char *program_usage_string = _(
|
|
Packit |
8ea169 |
"& [-v] [-c CONFFILE] [-r CHROOT] -d DIR\n"
|
|
Packit |
8ea169 |
"\n"
|
|
Packit |
8ea169 |
"Query package database and save package and component name"
|
|
Packit |
8ea169 |
);
|
|
Packit |
8ea169 |
enum {
|
|
Packit |
8ea169 |
OPT_v = 1 << 0,
|
|
Packit |
8ea169 |
OPT_d = 1 << 1,
|
|
Packit |
8ea169 |
OPT_c = 1 << 2,
|
|
Packit |
8ea169 |
OPT_r = 1 << 2,
|
|
Packit |
8ea169 |
};
|
|
Packit |
8ea169 |
/* Keep enum above and order of options below in sync! */
|
|
Packit |
8ea169 |
struct options program_options[] = {
|
|
Packit |
8ea169 |
OPT__VERBOSE(&g_verbose),
|
|
Packit |
8ea169 |
OPT_STRING('d', NULL, &dump_dir_name, "DIR" , _("Problem directory")),
|
|
Packit |
8ea169 |
OPT_STRING('c', NULL, &conf_filename, "CONFFILE", _("Configuration file")),
|
|
Packit |
8ea169 |
OPT_STRING('r', "chroot", &chroot, "CHROOT" , _("Use this directory as RPM root")),
|
|
Packit |
8ea169 |
OPT_END()
|
|
Packit |
8ea169 |
};
|
|
Packit |
8ea169 |
/*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
export_abrt_envvars(0);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_notice("Loading settings");
|
|
Packit |
8ea169 |
if (load_conf(conf_filename) != 0)
|
|
Packit |
8ea169 |
return 1; /* syntax error (logged already by load_conf) */
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
log_notice("Initializing rpm library");
|
|
Packit |
8ea169 |
rpm_init();
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GList *li;
|
|
Packit |
8ea169 |
for (li = settings_setOpenGPGPublicKeys; li != NULL; li = g_list_next(li))
|
|
Packit |
8ea169 |
{
|
|
Packit |
8ea169 |
log_notice("Loading GPG key '%s'", (char*)li->data);
|
|
Packit |
8ea169 |
rpm_load_gpgkey((char*)li->data);
|
|
Packit |
8ea169 |
}
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
int r = SavePackageDescriptionToDebugDump(dump_dir_name, chroot);
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
/* Close RPM database */
|
|
Packit |
8ea169 |
rpm_destroy();
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return r;
|
|
Packit |
8ea169 |
}
|