Skip to content

Commit

Permalink
provide all data required for compilation of uReport
Browse files Browse the repository at this point in the history
pkg_* files

Signed-off-by: Jakub Filak <jfilak@redhat.com>
  • Loading branch information
Jakub Filak committed May 2, 2014
1 parent 831e000 commit c9590e7
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 86 deletions.
1 change: 1 addition & 0 deletions abrt.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif
%{_bindir}/abrt-dump-oops
%{_bindir}/abrt-action-analyze-oops
%{_bindir}/abrt-action-save-kernel-data
%{_mandir}/man1/abrt-action-analyze-oops.1*

%files addon-vmcore
Expand Down
186 changes: 111 additions & 75 deletions src/daemon/abrt-action-save-package-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,112 +181,141 @@ static bool is_path_blacklisted(const char *path)
return false;
}

static struct pkg_envra *get_script_name(const char *cmdline, char **executable)
{
// 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 if the cmdline contains the whole path.
* Example: python /usr/bin/system-control-network
*/
struct pkg_envra *script_pkg = NULL;
char *script_name = get_argv1_if_full_path(cmdline);
if (script_name)
{
script_pkg = rpm_get_package_nvr(script_name, NULL);
if (script_pkg)
{
/* There is a well-formed script name in argv[1],
* and it does belong to some package.
* Replace executable
* with data pertaining to the script.
*/
*executable = script_name;
}
}

return script_pkg;
}


static int SavePackageDescriptionToDebugDump(const char *dump_dir_name)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
return 1;

char *analyzer = dd_load_text(dd, FILENAME_ANALYZER);
if (!strcmp(analyzer, "Kerneloops"))
{
dd_save_text(dd, FILENAME_PACKAGE, "kernel");
dd_save_text(dd, FILENAME_COMPONENT, "kernel");
dd_close(dd);
free(analyzer);
return 0;
}
free(analyzer);

char *cmdline = NULL;
char *executable = NULL;
char *rootdir = NULL;
char *script_name = NULL; /* only if "interpreter /path/to/script" */
char *package_short_name = NULL;
char *package_full_name = NULL;
struct pkg_envra *pkg_name = NULL;
char *component = NULL;
int error = 1;
/* note: "goto ret" statements below free all the above variables,
* but they don't dd_close(dd) */

char *analyzer = dd_load_text(dd, FILENAME_ANALYZER);
bool kernel = (strcmp(analyzer, "Kerneloops") == 0);
free(analyzer);
if (kernel)
{
package_full_name = xstrdup("kernel");
component = xstrdup("kernel");
}
else
{
cmdline = dd_load_text(dd, FILENAME_CMDLINE);
executable = dd_load_text(dd, FILENAME_EXECUTABLE);
rootdir = dd_load_text_ext(dd, FILENAME_ROOTDIR,
DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
cmdline = dd_load_text(dd, FILENAME_CMDLINE);
executable = dd_load_text(dd, FILENAME_EXECUTABLE);
rootdir = dd_load_text_ext(dd, FILENAME_ROOTDIR,
DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);

/* Close dd while we query package database. It can take some time,
* don't want to keep dd locked longer than necessary */
dd_close(dd);
/* Close dd while we query package database. It can take some time,
* don't want to keep dd locked longer than necessary */
dd_close(dd);

if (is_path_blacklisted(executable))
{
log("Blacklisted executable '%s'", executable);
goto ret; /* return 1 (failure) */
}
if (is_path_blacklisted(executable))
{
log("Blacklisted executable '%s'", executable);
goto ret; /* return 1 (failure) */
}

package_full_name = rpm_get_package_nvr(executable, rootdir);
if (!package_full_name)
pkg_name = rpm_get_package_nvr(executable, rootdir);
if (!pkg_name)
{
if (settings_bProcessUnpackaged)
{
if (settings_bProcessUnpackaged)
{
VERB2 log("Crash in unpackaged executable '%s', proceeding without packaging information", executable);
goto ret0; /* no error */
}
log("Executable '%s' doesn't belong to any package"
" and ProcessUnpackaged is set to 'no'",
executable
);
goto ret; /* return 1 (failure) */
VERB2 log("Crash in unpackaged executable '%s', proceeding without packaging information", executable);
goto ret0; /* no error */
}
log("Executable '%s' doesn't belong to any package"
" and ProcessUnpackaged is set to 'no'",
executable
);
goto ret; /* return 1 (failure) */
}

/* Check well-known interpreter names */
{
const char *basename = strrchr(executable, '/');
if (basename) basename++; else basename = executable;
/* Check well-known interpreter names */
{
const char *basename = strrchr(executable, '/');
if (basename) basename++; else basename = executable;

/* Add more interpreters as needed */
if (strcmp(basename, "python") == 0
|| strcmp(basename, "perl") == 0
) {
/* Add more interpreters as needed */
if (strcmp(basename, "python") == 0
|| strcmp(basename, "perl") == 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 if the cmdline contains the whole path.
* Example: python /usr/bin/system-control-network
/* Try to find package for the script by looking at argv[1].
* This will work only if the cmdline contains the whole path.
* Example: python /usr/bin/system-control-network
*/
struct pkg_envra *script_pkg = get_script_name(cmdline, &executable);
/* executable may have changed, check it again */
if (is_path_blacklisted(executable))
{
log("Blacklisted executable '%s'", executable);
goto ret; /* return 1 (failure) */
}
if (!script_pkg)
{
/* Script name is not absolute, or it doesn't
* belong to any installed package.
*/
char *script_pkg = NULL;
char *script_name = get_argv1_if_full_path(cmdline);
if (script_name)
{
script_pkg = rpm_get_package_nvr(script_name, NULL);
if (script_pkg)
{
/* There is a well-formed script name in argv[1],
* and it does belong to some package.
* Replace interpreter's package_full_name and executable
* with data pertaining to the script.
*/
free(package_full_name);
package_full_name = script_pkg;
executable = script_name;
/* executable has changed, check it again */
if (is_path_blacklisted(executable))
{
log("Blacklisted executable '%s'", executable);
goto ret; /* return 1 (failure) */
}
}
}
if (!script_pkg && !settings_bProcessUnpackaged)
if (!settings_bProcessUnpackaged)
{
log("Interpreter crashed, but no packaged script detected: '%s'", cmdline);
goto ret; /* return 1 (failure) */
}

/* Unpackaged script, but the settings says we want to keep it.
* BZ plugin wont allow to report this anyway, because component
* is missing, so there is no reason to mark it as not_reportable.
* Someone might want to use abrt to report it using ftp.
*/
goto ret0;
}

free_pkg_envra(pkg_name);
pkg_name = script_pkg;
}

package_short_name = get_package_name_from_NVR_or_NULL(package_full_name);
VERB2 log("Package:'%s' short:'%s'", package_full_name, package_short_name);
package_short_name = xasprintf("%s", pkg_name->p_name);
VERB1 log("Package:'%s' short:'%s'", pkg_name->p_nvr, package_short_name);

GList *li;

Expand Down Expand Up @@ -321,10 +350,17 @@ static int SavePackageDescriptionToDebugDump(const char *dump_dir_name)
goto ret; /* return 1 (failure) */
}

if (package_full_name)
if (pkg_name)
{
dd_save_text(dd, FILENAME_PACKAGE, package_full_name);
dd_save_text(dd, FILENAME_PACKAGE, pkg_name->p_nvr);
dd_save_text(dd, FILENAME_PKG_EPOCH, pkg_name->p_epoch);
dd_save_text(dd, FILENAME_PKG_NAME, pkg_name->p_name);
dd_save_text(dd, FILENAME_PKG_VERSION, pkg_name->p_version);
dd_save_text(dd, FILENAME_PKG_RELEASE, pkg_name->p_release);
dd_save_text(dd, FILENAME_PKG_ARCH, pkg_name->p_arch);
}


if (component)
{
dd_save_text(dd, FILENAME_COMPONENT, component);
Expand All @@ -340,7 +376,7 @@ static int SavePackageDescriptionToDebugDump(const char *dump_dir_name)
free(rootdir);
free(script_name);
free(package_short_name);
free(package_full_name);
free_pkg_envra(pkg_name);
free(component);

return error;
Expand Down
84 changes: 77 additions & 7 deletions src/daemon/rpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,34 @@ char* rpm_get_component(const char *filename, const char *rootdir_or_NULL)
return ret;
}

#define pkg_add_id(name) \
static inline int pkg_add_##name(Header header, struct pkg_envra *p) \
{ \
const char *errmsg = NULL; \
p->p_##name = headerFormat(header, "%{"#name"}", &errmsg); \
if (p->p_##name || !errmsg) \
return 0; \
\
error_msg("cannot get "#name": %s", errmsg); \
\
return -1; \
} \

pkg_add_id(epoch);
pkg_add_id(name);
pkg_add_id(version);
pkg_add_id(release);
pkg_add_id(arch);

// caller is responsible to free returned value
char* rpm_get_package_nvr(const char *filename, const char *rootdir_or_NULL)
struct pkg_envra *rpm_get_package_nvr(const char *filename, const char *rootdir_or_NULL)
{
char *nvr = NULL;
rpmts ts;
rpmdbMatchIterator iter;
Header header;

struct pkg_envra *p = NULL;

ts = rpmtsCreate();
/* This loop executes once (normally) or twice (if we detect chroot) */
while (1)
Expand Down Expand Up @@ -254,14 +274,64 @@ char* rpm_get_package_nvr(const char *filename, const char *rootdir_or_NULL)
rootdir_or_NULL = NULL;
}

const char *errmsg = NULL;
nvr = headerFormat(header, "%{NAME}-%{VERSION}-%{RELEASE}", &errmsg);
if (!nvr && errmsg)
error_msg("cannot get nvr. reason: %s", errmsg);


p = xzalloc(sizeof(*p));
int r;
r = pkg_add_epoch(header, p);
if (r)
goto error;
/*
* <npajkovs> hello, what's the difference between epoch '0' and '(none)'?
* <Panu> nothing really, a missing epoch is considered equal to zero epoch
*/
if (!strncmp(p->p_epoch, "(none)", strlen("(none)")))
{
free(p->p_epoch);
p->p_epoch = xstrdup("0");
}

r = pkg_add_name(header, p);
if (r)
goto error;

r = pkg_add_version(header, p);
if (r)
goto error;

r = pkg_add_release(header, p);
if (r)
goto error;

r = pkg_add_arch(header, p);
if (r)
goto error;

p->p_nvr = xasprintf("%s-%s-%s", p->p_name, p->p_version, p->p_release);

rpmdbFreeIterator(iter);
rpmtsFree(ts);
return p;

error:
free_pkg_envra(p);

rpmdbFreeIterator(iter);
error1:
rpmtsFree(ts);
return nvr;
return NULL;
}

void free_pkg_envra(struct pkg_envra *p)
{
if (!p)
return;

free(p->p_epoch);
free(p->p_name);
free(p->p_version);
free(p->p_release);
free(p->p_arch);
free(p->p_nvr);
free(p);
}
13 changes: 12 additions & 1 deletion src/daemon/rpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@
extern "C" {
#endif

struct pkg_envra {
char *p_nvr;
char *p_epoch;
char *p_name;
char *p_version;
char *p_release;
char *p_arch;
};

void free_pkg_envra(struct pkg_envra *p);

/**
* Checks if an application is modified by third party.
* @param pPackage A package name. The package contains the application.
Expand Down Expand Up @@ -64,7 +75,7 @@ int rpm_chk_fingerprint(const char* pkg);
* @param filename A file name.
* @return A package name (malloc'ed string)
*/
char* rpm_get_package_nvr(const char *filename, const char *rootdir_or_NULL);
struct pkg_envra *rpm_get_package_nvr(const char *filename, const char *rootdir_or_NULL);
/**
* Finds a main package for given file. This package contains particular
* file. If the file doesn't belong to any package, empty string is
Expand Down

0 comments on commit c9590e7

Please sign in to comment.