CERT Triage Tools 1.0 (INFO#208126) (re-send)
by Jonathan M. Foote
Hello,
I work on the Vulnerability Analysis team at CERT/CC (www.cert.org<http://www.cert.org>). We recently released an open source project that I developed, the CERT Triage Tools, and I thought it might be of interest to your team. From the CERT Triage Tools webpage (http://www.cert.org/vuls/discovery/triage.html):
'''
The CERT Triage Tools can be used to assist software vendors and analysts in identifying the impact of defects discovered through techniques such as fuzz testing and prioritizing their remediation in the software development process. The CERT Triage Tools include a GNU Debugger (GDB) extension called "exploitable" that classifies Linux application bugs by severity and a wrapper script for batch execution.
'''
The 'exploitable' GDB extension mentioned above is a Python script that can be used to determine how exploitable a crash is. I recently published a blog post with some more information on the extension and how to use it: http://www.cert.org/blogs/certcc/2012/04/cert_triage_tools_10.html
Josh Bressers and Steve Grubb, of Red Hat, have been investigating use of the tools by your organization. I have CC'd them on this message. (Josh and Steve: The first message I sent didn't post to the mailing list due to a clerical error on my part - feel free to ignore this re-send)
Regardless, I have been passively following the work your team has been doing and thought our tools might be useful to you. If you have any questions, comments, or ideas feel please feel free to drop me a line.
Thanks,
Jon Foote
11 years, 10 months
[PATCH] trac#522 : abrt vmcore plugin verbosity correction
by Jakub Filak
---
src/plugins/abrt-action-analyze-vmcore.in | 7 +++++--
src/plugins/abrt-action-install-debuginfo.in | 2 ++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/plugins/abrt-action-analyze-vmcore.in b/src/plugins/abrt-action-analyze-vmcore.in
index af606c4..c3f2e2e 100644
--- a/src/plugins/abrt-action-analyze-vmcore.in
+++ b/src/plugins/abrt-action-analyze-vmcore.in
@@ -25,7 +25,7 @@ if __name__ == "__main__":
vmlinux_di_path = ""
tmpdir = ""
vmcore = ""
- global verbose
+
help_text = _("Usage: {0} [-v[v]] [--core=VMCORE] [--tmpdir=TMPDIR] [--cache=CACHEDIR]").format(PROGNAME)
try:
opts, args = getopt.getopt(sys.argv[1:], "hvd", ["help", "tmpdir=", "cache=", "core="])
@@ -114,7 +114,10 @@ if __name__ == "__main__":
error_msg_and_die(_("Can't download required debuginfo"))
vmlinux_di_path = "{0}/usr/lib/debug/lib/modules/{1}/vmlinux".format(vmlinux_di_cachedir, ver)
else: # we need to use the suid wrapper, if we use the default cache
- downloader = Popen(["/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", "--size_mb=4096", "--exact={0}".format(vmlinux_di_path)], bufsize = -1)
+ downloader_args = ["/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", "--size_mb=4096", "--exact={0}".format(vmlinux_di_path)]
+ if verbose > 0:
+ downloader_args.append("-{0}".format("v"*verbose))
+ downloader = Popen(downloader_args, bufsize = -1)
res = downloader.wait()
if res != 0:
error_msg_and_die(_("Can't download required debuginfo"))
diff --git a/src/plugins/abrt-action-install-debuginfo.in b/src/plugins/abrt-action-install-debuginfo.in
index a6c39f3..a061fa6 100644
--- a/src/plugins/abrt-action-install-debuginfo.in
+++ b/src/plugins/abrt-action-install-debuginfo.in
@@ -134,6 +134,8 @@ if __name__ == "__main__":
missing=arg.split(':')
exact_fls = True
+ set_verbosity(verbose)
+
if not cachedirs:
try:
fp = open("@sysconfdir@/@PACKAGE_NAME(a)/plugins/CCpp.conf", "r")
--
1.7.7.6
11 years, 10 months
[PATCH abrt,libreport] reporter-ureport integration
by Jakub Filak
* added a new event named 'report_uReport'
* added a new XML configuration for reporter-uReport
* moved the 'report-gui' event from abrt:abrt_event.conf to
libreport:ureport_event.conf
Run, tested, please review :)
NOTE: patches are attached because the changes took place in two different
repositories
11 years, 11 months
[PATCH v2] track#546 : ureport url from an environment variable
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/ureport.c | 39 +++++++++++++++++++++++++++++++++++----
1 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index a8ac472..21dc58d 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -21,6 +21,31 @@
#include "internal_libreport.h"
#include "abrt_curl.h"
+/*
+ * uReport server configuration
+ */
+struct ureport_server_config
+{
+ const char *url; ///< Web service URL
+};
+
+/*
+ * Loads uReport configuration from various sources.
+ *
+ * Replaces a value of an already configured option only if the
+ * option was found in a configuration source.
+ *
+ * @param config a server configuration to be populated
+ */
+static void load_ureport_server_config(struct ureport_server_config *config)
+{
+ const char *environ;
+
+ environ = getenv("uReport_URL");
+ config->url = environ ? environ : config->url;
+}
+
+
enum response_type
{
UREPORT_SERVER_RESP_UNKNOWN_TYPE,
@@ -67,11 +92,15 @@ int main(int argc, char **argv)
{
abrt_init(argv);
- const char *dump_dir_path = ".", *url = "https://retrace.fedoraproject.org/faf/reports/new/";
+ struct ureport_server_config config = {
+ .url = "https://retrace.fedoraproject.org/faf/reports/new/",
+ };
+
+ const char *dump_dir_path = ".";
struct options program_options[] = {
OPT__VERBOSE(&g_verbose),
OPT__DUMP_DIR(&dump_dir_path),
- OPT_STRING('u', "url", &url, "URL", _("Specify url")),
+ OPT_STRING('u', "url", &config.url, "URL", _("Specify url")),
OPT_END(),
};
@@ -86,13 +115,15 @@ int main(int argc, char **argv)
if (!dd)
xfunc_die();
+ load_ureport_server_config(&config);
+
problem_data_t *pd = create_problem_data_from_dump_dir(dd);
dd_close(dd);
if (!pd)
xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
abrt_post_state_t *post_state = NULL;
- post_state = post_ureport(pd, url);
+ post_state = post_ureport(pd, config.url);
free_problem_data(pd);
if (post_state->http_resp_code != 200)
@@ -100,7 +131,7 @@ int main(int argc, char **argv)
char *errmsg = post_state->curl_error_msg;
if (errmsg && *errmsg)
{
- error_msg("%s '%s'", errmsg, url);
+ error_msg("%s '%s'", errmsg, config.url);
free_abrt_post_state(post_state);
return 1;
}
--
1.7.7.6
11 years, 11 months
[PATCH] track#546 : ureport url from an environment variable
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/ureport.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index a8ac472..adcd14c 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -82,6 +82,12 @@ int main(int argc, char **argv)
);
parse_opts(argc, argv, program_options, program_usage_string);
+
+ {
+ const char *environ = getenv("uReport_URL");
+ url = environ ? environ : url;
+ }
+
struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
if (!dd)
xfunc_die();
--
1.7.7.6
11 years, 11 months
[PATCH v3] rhbz#622773 : abrt-dbus new high-level problem query functions
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 155 insertions(+), 4 deletions(-)
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index 6bdca48..7c976cd 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -38,6 +38,14 @@ static const gchar introspection_xml[] =
" <method name='DeleteProblem'>"
" <arg type='as' name='problem_dir' direction='in'/>"
" </method>"
+ " <method name='FindProblemByElementInTimeRange'>"
+ " <arg type='s' name='element' direction='in'/>"
+ " <arg type='s' name='value' direction='in'/>"
+ " <arg type='t' name='timestamp_from' direction='in'/>"
+ " <arg type='t' name='timestamp_to' direction='in'/>"
+ " <arg type='b' name='all_users' direction='in'/>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
" <method name='Quit' />"
" </interface>"
"</node>";
@@ -154,7 +162,50 @@ static int dir_accessible_by_uid(const char* dir_path, uid_t uid)
return 0;
}
-static GList* scan_directory(const char *path, uid_t caller_uid)
+/*
+ * Structure for simple conditions based on problem fields
+ */
+struct problem_condition
+{
+ /* a name of filed required by evaluate function */
+ const char *field_name;
+ /* extra data passed to evaluate function */
+ const void *args;
+ /* evaluate function returning TRUE if condition was passed */
+ bool (*evaluate)(const char *, const void *);
+};
+
+/*
+ * Evaluates a NULL-terminated list of problem conditions as a logical conjunction
+ */
+static bool problem_condition_evaluate_and(struct dump_dir *dd,
+ const struct problem_condition *const *condition)
+{
+ /* We stop on the first FALSE condition */
+ while (*condition != NULL)
+ {
+ const struct problem_condition *c = *condition;
+ char *field_data = dd_load_text(dd, c->field_name);
+ bool value = c->evaluate(field_data, c->args);
+ free(field_data);
+ if (!value)
+ return false;
+ ++condition;
+ }
+
+ return true;
+}
+
+/*
+ * Goes through all problems and selects only problems accessible by caller_uid and
+ * problems for which an and_filter gets TRUE
+ *
+ * @param condition a NULL-terminated list of problem conditions evaluated
+ * as conjunction, can be NULL (means always TRUE)
+ */
+static GList* scan_directory(const char *path,
+ uid_t caller_uid,
+ const struct problem_condition *const *condition)
{
GList *list = NULL;
@@ -189,8 +240,11 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
*/
if (dd && (caller_uid == 0 || statbuf.st_mode & S_IROTH || uid_in_group(caller_uid, statbuf.st_gid)))
{
- list = g_list_prepend(list, full_name);
- full_name = NULL;
+ if (problem_condition_evaluate_and(dd, condition))
+ {
+ list = g_list_prepend(list, full_name);
+ full_name = NULL;
+ }
}
dd_close(dd); //doesn't fail even if dd == NULL
}
@@ -204,9 +258,82 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
return g_list_reverse(list);
}
+/* Self explaining time interval structure */
+struct time_interval
+{
+ unsigned long from;
+ unsigned long to;
+};
+
+/*
+ * A problem condition evaluate function for checking of the TIME field against
+ * an allowed interval
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer to an instance of struct time_interval
+ * @return TRUE if a field value is in a specified interval; otherwise FALSE
+ */
+static bool time_interval_problem_condition(const char *field_data, const void* args)
+{
+ const struct time_interval *const interval = (const struct time_interval *)args;
+ const time_t timestamp = atol(field_data);
+
+ return interval->from <= timestamp && timestamp <= interval->to;
+}
+
+/*
+ * A problem condition evaluate function passed if strings are equal
+ *
+ * @param field_data a content of a field
+ * @param args a checked string
+ * @return TRUE if both strings are equal; otherwise FALSE
+ */
+static bool equal_string_problem_condition(const char *field_data, const void* args)
+{
+ return !strcmp(field_data, (const char *)args);
+}
+
static GVariant *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
{
- GList *dirs = scan_directory(dump_location, uid);
+ GList *dirs = scan_directory(dump_location, uid, NULL);
+
+ return variant_from_string_list(dirs);
+}
+
+/*
+ * Finds problems with the specified element and which were created in the interval
+ */
+static GVariant *get_problem_dirs_for_element_in_time(uid_t uid,
+ const char *element,
+ const char *value,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location)
+{
+ const struct problem_condition elementc = {
+ .field_name = element,
+ .args = value,
+ .evaluate = equal_string_problem_condition,
+ };
+
+ const struct time_interval interval = {
+ .from = timestamp_from,
+ .to = timestamp_to
+ };
+
+ const struct problem_condition timec = {
+ .field_name = FILENAME_TIME,
+ .args = &interval,
+ .evaluate = time_interval_problem_condition
+ };
+
+ const struct problem_condition *const condition[] = {
+ &elementc,
+ &timec,
+ NULL
+ };
+
+ GList *dirs = scan_directory(dump_location, uid, condition);
return variant_from_string_list(dirs);
}
@@ -454,6 +581,26 @@ static void handle_method_call(GDBusConnection *connection,
return;
}
+ else if (g_strcmp0(method_name, "FindProblemByElementInTimeRange") == 0)
+ {
+ const char* element;
+ const char* value;
+ unsigned long timestamp_from;
+ unsigned long timestamp_to;
+ bool all;
+
+ g_variant_get(parameters, "(ssttb)", &element, &value, ×tamp_from, ×tamp_to, &all);
+
+ if (all && polkit_check_authorization_dname(caller, "org.freedesktop.problems.getall") == PolkitYes)
+ caller_uid = 0;
+
+ response = get_problem_dirs_for_element_in_time(caller_uid, element, value, timestamp_from,
+ timestamp_to, g_settings_dump_location);
+
+ g_dbus_method_invocation_return_value(invocation, response);
+ return;
+ }
+
else if (g_strcmp0(method_name, "Quit") == 0)
{
VERB1 log("Quit");
@@ -576,6 +723,8 @@ int main (int argc, char *argv[])
NULL,
NULL);
+ load_abrt_conf();
+
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
@@ -585,6 +734,8 @@ int main (int argc, char *argv[])
g_dbus_node_info_unref(introspection_data);
+ free_abrt_conf_data();
+
return 0;
}
--
1.7.7.6
11 years, 11 months
[PATCH v2] rhbz#622773 : abrt-dbus new high-level problem query functions
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 205 insertions(+), 4 deletions(-)
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index 6bdca48..cfbc086 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -38,6 +38,14 @@ static const gchar introspection_xml[] =
" <method name='DeleteProblem'>"
" <arg type='as' name='problem_dir' direction='in'/>"
" </method>"
+ " <method name='FindProblemByElementInTimeRange'>"
+ " <arg type='s' name='element' direction='in'/>"
+ " <arg type='s' name='value' direction='in'/>"
+ " <arg type='t' name='timestamp_from' direction='in'/>"
+ " <arg type='t' name='timestamp_to' direction='in'/>"
+ " <arg type='b' name='all_users' direction='in'/>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
" <method name='Quit' />"
" </interface>"
"</node>";
@@ -154,7 +162,50 @@ static int dir_accessible_by_uid(const char* dir_path, uid_t uid)
return 0;
}
-static GList* scan_directory(const char *path, uid_t caller_uid)
+/*
+ * Structure for simple conditions based on problem fields
+ */
+struct problem_condition
+{
+ /* a name of filed required by evaluate function */
+ const char *field_name;
+ /* extra data passed to evaluate function */
+ const void *args;
+ /* evaluate function returning TRUE if condition was passed */
+ bool (*evaluate)(const char *, const void *);
+};
+
+/*
+ * Evaluates a NULL-terminated list of problem conditions as a logical conjunction
+ */
+static bool problem_condition_evaluate_and(struct dump_dir *dd,
+ const struct problem_condition *const *condition)
+{
+ /* We stop on the first FALSE condition */
+ while (*condition != NULL)
+ {
+ const struct problem_condition *c = *condition;
+ char *field_data = dd_load_text(dd, c->field_name);
+ bool value = c->evaluate(field_data, c->args);
+ free(field_data);
+ if (!value)
+ return false;
+ ++condition;
+ }
+
+ return true;
+}
+
+/*
+ * Goes through all problems and selects only problems accessible by caller_uid and
+ * problems for which an and_filter gets TRUE
+ *
+ * @param condition a NULL-terminated list of problem conditions evaluated
+ * as conjunction, can be NULL (means always TRUE)
+ */
+static GList* scan_directory(const char *path,
+ uid_t caller_uid,
+ const struct problem_condition *const *condition)
{
GList *list = NULL;
@@ -189,8 +240,11 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
*/
if (dd && (caller_uid == 0 || statbuf.st_mode & S_IROTH || uid_in_group(caller_uid, statbuf.st_gid)))
{
- list = g_list_prepend(list, full_name);
- full_name = NULL;
+ if (problem_condition_evaluate_and(dd, condition))
+ {
+ list = g_list_prepend(list, full_name);
+ full_name = NULL;
+ }
}
dd_close(dd); //doesn't fail even if dd == NULL
}
@@ -204,9 +258,120 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
return g_list_reverse(list);
}
+/* Self explaining time interval structure */
+struct time_interval
+{
+ unsigned long from;
+ unsigned long to;
+};
+
+/*
+ * A problem condition evaluate function for checking of the TIME field against
+ * an allowed interval
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer to an instance of struct time_interval
+ * @return TRUE if a field value is in a specified interval; otherwise FALSE
+ */
+static bool time_interval_problem_condition(const char *field_data, const void* args)
+{
+ if (!field_data)
+ return FALSE;
+
+ const struct time_interval *const interval = (const struct time_interval *)args;
+ const time_t timestamp = atol(field_data);
+
+ return interval->from <= timestamp && timestamp <= interval->to;
+}
+
+/*
+ * A problem condition evaluate function passed if strings are equal
+ *
+ * @param field_data a content of a field
+ * @param args a checked string
+ * @return TRUE if both strings are equal; otherwise FALSE
+ */
+static bool equal_string_problem_condition(const char *field_data, const void* args)
+{
+ return (field_data == NULL && args == NULL)
+ || (field_data != NULL && !strcmp(field_data, (const char *)args));
+}
+
+/*
+ * A problem condition evaluate function passed if args string is substring
+ * of element field data
+ *
+ * @param field_data a content of a field
+ * @param args a checked string
+ * @return TRUE if args is substring of field_data; otherwise FALSE
+ */
+static bool substring_problem_condition(const char *field_data, const void* args)
+{
+ /* BEWARE : formally empty string IS ALWAYS substring of any string */
+ /* but it is NOT VALID in our case */
+ return field_data != NULL && strstr(field_data, (const char *)args);
+}
+
static GVariant *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
{
- GList *dirs = scan_directory(dump_location, uid);
+ GList *dirs = scan_directory(dump_location, uid, NULL);
+
+ return variant_from_string_list(dirs);
+}
+
+/*
+ * Provides basic initialization according to required element
+ *
+ * @param condition a problem condition structure
+ * @param element a name of problem dir field
+ * @param value a string for which we are looking for
+ */
+static void initialize_element_condition(struct problem_condition *condition,
+ const char *element,
+ const char *value)
+{
+ condition->field_name = element;
+ condition->args = value;
+
+ /* use substring evaluate function for CGROUP element */
+ if (strcmp(element, FILENAME_CGROUP) == 0)
+ condition->evaluate = substring_problem_condition;
+ else
+ /* an evaluate function is string equality by default */
+ condition->evaluate = equal_string_problem_condition;
+}
+
+/*
+ * Finds problems with the specified element and which were created in the interval
+ */
+static GVariant *get_problem_dirs_for_element_in_time(uid_t uid,
+ const char *element,
+ const char *value,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location)
+{
+ const struct time_interval interval = {
+ .from = timestamp_from,
+ .to = timestamp_to
+ };
+
+ const struct problem_condition timec = {
+ .field_name = FILENAME_TIME,
+ .args = &interval,
+ .evaluate = time_interval_problem_condition
+ };
+
+ struct problem_condition elementc;
+ initialize_element_condition(&elementc, element, value);
+
+ const struct problem_condition *const condition[] = {
+ &elementc,
+ &timec,
+ NULL
+ };
+
+ GList *dirs = scan_directory(dump_location, uid, condition);
return variant_from_string_list(dirs);
}
@@ -454,6 +619,42 @@ static void handle_method_call(GDBusConnection *connection,
return;
}
+ else if (g_strcmp0(method_name, "FindProblemByElementInTimeRange") == 0)
+ {
+ const char* element;
+ const char* value;
+ unsigned long timestamp_from;
+ unsigned long timestamp_to;
+ bool all;
+
+ g_variant_get(parameters, "(ssttb)", &element, &value, ×tamp_from, ×tamp_to, &all);
+
+ if (strlen(element) == 0)
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.InvalidElement",
+ _("Empty Element Name"));
+ return;
+ }
+
+ if (all && polkit_check_authorization_dname(caller, "org.freedesktop.problems.getall") == PolkitYes)
+ caller_uid = 0;
+
+ /* FIXME : Temporary until we decide how to handle this */
+ if (!g_settings_dump_location)
+ g_settings_dump_location = (char*)"/var/spool/abrt";
+
+ response = get_problem_dirs_for_element_in_time(caller_uid,
+ element,
+ value,
+ timestamp_from,
+ timestamp_to,
+ g_settings_dump_location);
+
+ g_dbus_method_invocation_return_value(invocation, response);
+ return;
+ }
+
else if (g_strcmp0(method_name, "Quit") == 0)
{
VERB1 log("Quit");
--
1.7.7.6
11 years, 11 months
[PATCH] rhbz#622773 : abrt-dbus new high-level problem query functions
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 217 insertions(+), 4 deletions(-)
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index e9f3d86..0fd717c 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -38,6 +38,20 @@ static const gchar introspection_xml[] =
" <method name='DeleteProblem'>"
" <arg type='as' name='problem_dir' direction='in'/>"
" </method>"
+ " <method name='FindProblemByPID'>"
+ " <arg type='u' name='pid' direction='in'/>"
+ " <arg type='t' name='timestamp_from' direction='in'/>"
+ " <arg type='t' name='timestamp_to' direction='in'/>"
+ " <arg type='b' name='all_users' direction='in'/>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
+ " <method name='FindProblemByCGroup'>"
+ " <arg type='s' name='group' direction='in'/>"
+ " <arg type='t' name='timestamp_from' direction='in'/>"
+ " <arg type='t' name='timestamp_to' direction='in'/>"
+ " <arg type='b' name='all_users' direction='in'/>"
+ " <arg type='as' name='response' direction='out'/>"
+ " </method>"
" <method name='Quit' />"
" </interface>"
"</node>";
@@ -154,7 +168,56 @@ static int dir_accessible_by_uid(const char* dir_path, uid_t uid)
return 0;
}
-static GList* scan_directory(const char *path, uid_t caller_uid)
+/*
+ * Structure for simple conditions based on problem fields
+ */
+struct problem_condition
+{
+ /* a name of filed required by evaluate function */
+ const char *field_name;
+ /* extra data passed to evaluate function */
+ const void *args;
+ /* evaluate function returning TRUE if condition was passed */
+ bool (*evaluate)(const char *, const void *);
+};
+
+/*
+ * Evaluates a NULL-terminated list of problem conditions as a logical conjunction
+ */
+static bool problem_condition_evaluate_and(struct dump_dir *dd,
+ const struct problem_condition *const *condition)
+{
+ bool value = TRUE;
+
+ /* the NULL condition means ALWAYS PASSED */
+ if (condition != NULL)
+ {
+ /* loop cycle is stopped if accepted is false */
+ /* thus one FALSE returned from evaluate() causes return FALSE */
+ while (value && *condition)
+ {
+ const struct problem_condition *const c = *condition;
+ const char *const field_data = dd_load_text(dd, c->field_name);
+
+ value = c->evaluate(field_data, c->args);
+
+ ++condition;
+ }
+ }
+
+ return value;
+}
+
+/*
+ * Goes through all problems and selects only problems accessible by caller_uid and
+ * problems for which an and_filter gets TRUE
+ *
+ * @param condition a NULL-terminated list of problem conditions evaluated
+ * as conjunction, can be NULL (means always TRUE)
+ */
+static GList* scan_directory(const char *path,
+ uid_t caller_uid,
+ const struct problem_condition *const *condition)
{
GList *list = NULL;
@@ -189,8 +252,11 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
*/
if (dd && (caller_uid == 0 || statbuf.st_mode & S_IROTH || uid_in_group(caller_uid, statbuf.st_gid)))
{
- list = g_list_prepend(list, full_name);
- full_name = NULL;
+ if (problem_condition_evaluate_and(dd, condition))
+ {
+ list = g_list_prepend(list, full_name);
+ full_name = NULL;
+ }
}
dd_close(dd); //doesn't fail even if dd == NULL
}
@@ -204,9 +270,104 @@ static GList* scan_directory(const char *path, uid_t caller_uid)
return g_list_reverse(list);
}
+/*
+ * A problem condition evaluate function checking a value of the PID field
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer to a checked pid
+ * @return TRUE if a field value is the same pid as a required pid; otherwise FALSE
+ */
+static bool pid_problem_condition(const char *field_data, const void* args)
+{
+ const pid_t pid = *(const pid_t*)args;
+ return field_data != NULL && atoi(field_data) == pid;
+}
+
+/* Self explaining time interval structure */
+struct time_interval
+{
+ unsigned long from;
+ unsigned long to;
+};
+
+/*
+ * A problem condition evaluate function for checking of the TIME field against
+ * an allowed interval
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer to an instance of struct time_interval
+ * @return TRUE if a field value is in a specified interval; otherwise FALSE
+ */
+static bool time_interval_problem_condition(const char *field_data, const void* args)
+{
+ if (!field_data)
+ return FALSE;
+
+ const struct time_interval *const interval = (const struct time_interval *)args;
+ const time_t timestamp = atol(field_data);
+
+ return interval->from <= timestamp && timestamp <= interval->to;
+}
+
+/*
+ * A problem condition evaluate function for checking a value of the CGROUP
+ * field
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer string with cgroup
+ * @return TRUE if a specified cgroup is in a field value; otherwise FALSE
+ */
+static bool cgroup_problem_condition(const char *field_data, const void* args)
+{
+ /* Hope that any cgroup cannot be substring of an another cgroup */
+ return field_data != NULL && strstr(field_data, (const char *)args);
+}
+
static GVariant *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
{
- GList *dirs = scan_directory(dump_location, uid);
+ GList *dirs = scan_directory(dump_location, uid, NULL);
+
+ return variant_from_string_list(dirs);
+}
+
+/*
+ * Finds problems with the pid and which were created in the interval
+ */
+static GVariant *get_problem_dirs_for_pid_in_time(uid_t uid,
+ pid_t pid,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location)
+{
+ const struct problem_condition pidc = {FILENAME_PID, &pid, pid_problem_condition};
+
+ const struct time_interval interval = {timestamp_from, timestamp_to};
+ const struct problem_condition timec = {FILENAME_TIME, &interval, time_interval_problem_condition};
+
+ const struct problem_condition *const condition[] = {&pidc, &timec, NULL};
+
+ GList *dirs = scan_directory(dump_location, uid, condition);
+
+ return variant_from_string_list(dirs);
+}
+
+/*
+ * Finds problems with the cgroup and which were created in the interval
+ */
+static GVariant *get_problem_dirs_for_cgroup_in_time(uid_t uid,
+ const char* cgroup,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location)
+{
+ const struct problem_condition cgroupc = {FILENAME_CGROUP, cgroup, cgroup_problem_condition};
+
+ const struct time_interval interval = {timestamp_from, timestamp_to};
+ const struct problem_condition timec = {FILENAME_TIME, &interval, time_interval_problem_condition};
+
+ const struct problem_condition *const condition[] = {&cgroupc, &timec, NULL};
+
+ GList *dirs = scan_directory(dump_location, uid, condition);
return variant_from_string_list(dirs);
}
@@ -454,6 +615,58 @@ static void handle_method_call(GDBusConnection *connection,
return;
}
+ else if (g_strcmp0(method_name, "FindProblemByPID") == 0)
+ {
+ unsigned int pid;
+ unsigned long timestamp_from;
+ unsigned long timestamp_to;
+ bool all;
+
+ g_variant_get(parameters, "(uttb)", &pid, ×tamp_from, ×tamp_to, &all);
+
+ if (all && polkit_check_authorization_dname(caller, "org.freedesktop.problems.getall") == PolkitYes)
+ caller_uid = 0;
+
+ /* FIXME : Temporary until we decide how to handle this */
+ if (!g_settings_dump_location)
+ g_settings_dump_location = (char*)"/var/spool/abrt";
+
+ response = get_problem_dirs_for_pid_in_time(caller_uid,
+ pid,
+ timestamp_from,
+ timestamp_to,
+ g_settings_dump_location);
+
+ g_dbus_method_invocation_return_value(invocation, response);
+ return;
+ }
+
+ else if (g_strcmp0(method_name, "FindProblemByCGroup") == 0)
+ {
+ gchar *cgroup;
+ unsigned long timestamp_from;
+ unsigned long timestamp_to;
+ bool all;
+
+ g_variant_get(parameters, "(sttb)", &cgroup, ×tamp_from, ×tamp_to, &all);
+
+ if (all && polkit_check_authorization_dname(caller, "org.freedesktop.problems.getall") == PolkitYes)
+ caller_uid = 0;
+
+ /* FIXME : Temporary until we decide how to handle this */
+ if (!g_settings_dump_location)
+ g_settings_dump_location = (char*)"/var/spool/abrt";
+
+ response = get_problem_dirs_for_cgroup_in_time(caller_uid,
+ cgroup,
+ timestamp_from,
+ timestamp_to,
+ g_settings_dump_location);
+
+ g_dbus_method_invocation_return_value(invocation, response);
+ return;
+ }
+
else if (g_strcmp0(method_name, "Quit") == 0)
{
VERB1 log("Quit");
--
1.7.7.6
11 years, 11 months
[PATCH] track#542 : reporter-ureport uploads ureport files as html form does
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/lib/abrt_curl.c | 21 ++++++++++++++++++++-
src/lib/abrt_curl.h | 11 +++++++++++
src/lib/json.c | 4 ++--
src/plugins/ureport.c | 4 ++++
4 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/lib/abrt_curl.c b/src/lib/abrt_curl.c
index 9ec77d1..1ae773d 100644
--- a/src/lib/abrt_curl.c
+++ b/src/lib/abrt_curl.c
@@ -362,6 +362,24 @@ abrt_post(abrt_post_state_t *state,
//FIXME:
error_msg_and_die("out of memory or read error (curl_formadd error code: %d)", (int)curlform_err);
xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
+ } else if (data_size == ABRT_POST_DATA_STRING_AS_FORM_DATA) {
+ CURLFORMcode curlform_err = curl_formadd(&post, &last,
+ CURLFORM_PTRNAME, "file", // element name
+ // curl bug - missing filename
+ // http://curl.haxx.se/mail/lib-2011-07/0176.html
+ // https://github.com/bagder/curl/commit/45d883d
+ // fixed in curl-7.22.0~144
+ // tested with curl-7.24.0-3
+ // should be working on F17
+ CURLFORM_BUFFER, "*buffer*", // provides filename
+ CURLFORM_BUFFERPTR, data,
+ CURLFORM_BUFFERLENGTH, (long)strlen(data),
+//FIXME: what if file size doesn't fit in long?
+ CURLFORM_CONTENTTYPE, content_type,
+ CURLFORM_END);
+ if (curlform_err != 0)
+ error_msg_and_die("out of memory or read error (curl_formadd error code: %d)", (int)curlform_err);
+ xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
} else {
// .. from a blob in memory
xcurl_easy_setopt_ptr(handle, CURLOPT_POSTFIELDS, data);
@@ -375,7 +393,8 @@ abrt_post(abrt_post_state_t *state,
struct curl_slist *httpheader_list = NULL;
// Override "Content-Type:"
- if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA)
+ if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA
+ && data_size != ABRT_POST_DATA_STRING_AS_FORM_DATA)
{
char *content_type_header = xasprintf("Content-Type: %s", content_type);
// Note: curl_slist_append() copies content_type_header
diff --git a/src/lib/abrt_curl.h b/src/lib/abrt_curl.h
index dfca303..ca3c5b8 100644
--- a/src/lib/abrt_curl.h
+++ b/src/lib/abrt_curl.h
@@ -60,6 +60,7 @@ enum {
ABRT_POST_DATA_STRING = -1,
ABRT_POST_DATA_FROMFILE = -2,
ABRT_POST_DATA_FROMFILE_AS_FORM_DATA = -3,
+ ABRT_POST_DATA_STRING_AS_FORM_DATA = -4,
};
int
abrt_post(abrt_post_state_t *state,
@@ -79,6 +80,16 @@ abrt_post_string(abrt_post_state_t *state,
str, ABRT_POST_DATA_STRING);
}
static inline int
+abrt_post_string_as_form_data(abrt_post_state_t *state,
+ const char *url,
+ const char *content_type,
+ const char **additional_headers,
+ const char *str)
+{
+ return abrt_post(state, url, content_type, additional_headers,
+ str, ABRT_POST_DATA_STRING_AS_FORM_DATA);
+}
+static inline int
abrt_post_file(abrt_post_state_t *state,
const char *url,
const char *content_type,
diff --git a/src/lib/json.c b/src/lib/json.c
index 2adf4ee..3bf3844 100644
--- a/src/lib/json.c
+++ b/src/lib/json.c
@@ -237,14 +237,14 @@ abrt_post_state_t *post_ureport(problem_data_t *pd, const char *ureport_url)
| ABRT_POST_WANT_ERROR_MSG);
static const char *headers[] = {
- "Accept: text/plain",
+ "Accept: application/json",
"Connection: close",
NULL,
};
char *json_ureport = new_json_ureport(pd);
- abrt_post_string(post_state, ureport_url, "application/json",
+ abrt_post_string_as_form_data(post_state, ureport_url, "application/json",
headers, json_ureport);
free(json_ureport);
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index f0a6428..ed01cc7 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -63,12 +63,16 @@ int main(int argc, char **argv)
}
}
+ // TODO : parse JSON response
char *line = strtok(post_state->body, "\n");
+ VERB2 log("Response:\n----\n%s\n----", line);
+
int ret = 0;
while (line)
{
if (!prefixcmp(line, "ERROR "))
{
+ log("%s", line);
ret = 1;
break;
}
--
1.7.7.6
11 years, 11 months