Blame SOURCES/openscap-1.3.3-systemdunitdependency-probe-segfault.patch

cf36c6
diff --git a/src/OVAL/probes/unix/linux/systemdunitdependency.c b/src/OVAL/probes/unix/linux/systemdunitdependency.c
cf36c6
index 2f194ce07..e2cbdb7d2 100644
cf36c6
--- a/src/OVAL/probes/unix/linux/systemdunitdependency.c
cf36c6
+++ b/src/OVAL/probes/unix/linux/systemdunitdependency.c
cf36c6
@@ -37,6 +37,8 @@
cf36c6
 #include "common/list.h"
cf36c6
 #include <string.h>
cf36c6
 
cf36c6
+static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units);
cf36c6
+
cf36c6
 static char *get_property_by_unit_path(DBusConnection *conn, const char *unit_path, const char *property)
cf36c6
 {
cf36c6
 	DBusMessage *msg = NULL;
cf36c6
@@ -135,7 +137,38 @@ static bool is_unit_name_a_target(const char *unit)
cf36c6
 	return strncmp(unit + len - suffix_len, suffix, suffix_len) == 0;
cf36c6
 }
cf36c6
 
cf36c6
-static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, int(*callback)(const char *, void *), void *cbarg, bool include_requires, bool include_wants)
cf36c6
+static int add_unit_dependency(const char *dependency, SEXP_t *item, struct oscap_htable *visited_units)
cf36c6
+{
cf36c6
+	if (oscap_htable_get(visited_units, dependency) != NULL) {
cf36c6
+		return 1;
cf36c6
+	}
cf36c6
+	oscap_htable_add(visited_units, dependency, (void *) true);
cf36c6
+	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
cf36c6
+	probe_item_ent_add(item, "dependency", NULL, se_dependency);
cf36c6
+	SEXP_free(se_dependency);
cf36c6
+	return 0;
cf36c6
+}
cf36c6
+
cf36c6
+static void process_unit_property(const char *property, DBusConnection *conn, const char *path, SEXP_t *item, struct oscap_htable *visited_units)
cf36c6
+{
cf36c6
+	char *values_s = get_property_by_unit_path(conn, path, property);
cf36c6
+	if (values_s) {
cf36c6
+		char **values = oscap_split(values_s, ", ");
cf36c6
+		for (int i = 0; values[i] != NULL; ++i) {
cf36c6
+			if (oscap_strcmp(values[i], "") == 0) {
cf36c6
+				continue;
cf36c6
+			}
cf36c6
+
cf36c6
+			if (add_unit_dependency(values[i], item, visited_units) == 0) {
cf36c6
+				get_all_dependencies_by_unit(conn, values[i], item, visited_units);
cf36c6
+			}
cf36c6
+		}
cf36c6
+		free(values);
cf36c6
+	}
cf36c6
+	free(values_s);
cf36c6
+}
cf36c6
+
cf36c6
+static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit, SEXP_t *item, struct oscap_htable *visited_units)
cf36c6
 {
cf36c6
 	if (!unit || strcmp(unit, "(null)") == 0)
cf36c6
 		return;
cf36c6
@@ -146,66 +179,12 @@ static void get_all_dependencies_by_unit(DBusConnection *conn, const char *unit,
cf36c6
 
cf36c6
 	char *path = get_path_by_unit(conn, unit);
cf36c6
 
cf36c6
-	if (include_requires) {
cf36c6
-		char *requires_s = get_property_by_unit_path(conn, path, "Requires");
cf36c6
-		if (requires_s) {
cf36c6
-			char **requires = oscap_split(requires_s, ", ");
cf36c6
-			for (int i = 0; requires[i] != NULL; ++i) {
cf36c6
-				if (oscap_strcmp(requires[i], "") == 0)
cf36c6
-					continue;
cf36c6
-
cf36c6
-				if (callback(requires[i], cbarg) == 0) {
cf36c6
-					get_all_dependencies_by_unit(conn, requires[i],
cf36c6
-									callback, cbarg,
cf36c6
-									include_requires, include_wants);
cf36c6
-				} else {
cf36c6
-					free(requires);
cf36c6
-					free(requires_s);
cf36c6
-					free(path);
cf36c6
-					return;
cf36c6
-				}
cf36c6
-			}
cf36c6
-			free(requires);
cf36c6
-		}
cf36c6
-		free(requires_s);
cf36c6
-	}
cf36c6
-
cf36c6
-	if (include_wants) {
cf36c6
-		char *wants_s = get_property_by_unit_path(conn, path, "Wants");
cf36c6
-		if (wants_s)
cf36c6
-		{
cf36c6
-			char **wants = oscap_split(wants_s, ", ");
cf36c6
-			for (int i = 0; wants[i] != NULL; ++i) {
cf36c6
-				if (oscap_strcmp(wants[i], "") == 0)
cf36c6
-					continue;
cf36c6
-
cf36c6
-				if (callback(wants[i], cbarg) == 0) {
cf36c6
-					get_all_dependencies_by_unit(conn, wants[i],
cf36c6
-									callback, cbarg,
cf36c6
-									include_requires, include_wants);
cf36c6
-				} else {
cf36c6
-					free(wants);
cf36c6
-					free(wants_s);
cf36c6
-					free(path);
cf36c6
-					return;
cf36c6
-				}
cf36c6
-			}
cf36c6
-			free(wants);
cf36c6
-		}
cf36c6
-		free(wants_s);
cf36c6
-	}
cf36c6
+	process_unit_property("Requires", conn, path, item, visited_units);
cf36c6
+	process_unit_property("Wants", conn, path, item, visited_units);
cf36c6
 
cf36c6
 	free(path);
cf36c6
 }
cf36c6
 
cf36c6
-static int dependency_callback(const char *dependency, void *cbarg)
cf36c6
-{
cf36c6
-	SEXP_t *item = (SEXP_t *)cbarg;
cf36c6
-	SEXP_t *se_dependency = SEXP_string_new(dependency, strlen(dependency));
cf36c6
-	probe_item_ent_add(item, "dependency", NULL, se_dependency);
cf36c6
-	return 0;
cf36c6
-}
cf36c6
-
cf36c6
 static int unit_callback(const char *unit, void *cbarg)
cf36c6
 {
cf36c6
 	struct unit_callback_vars *vars = (struct unit_callback_vars *)cbarg;
cf36c6
@@ -221,8 +200,9 @@ static int unit_callback(const char *unit, void *cbarg)
cf36c6
 					 "unit", OVAL_DATATYPE_SEXP, se_unit,
cf36c6
 					 NULL);
cf36c6
 
cf36c6
-	get_all_dependencies_by_unit(vars->dbus_conn, unit,
cf36c6
-				     dependency_callback, item, true, true);
cf36c6
+	struct oscap_htable *visited_units = oscap_htable_new();
cf36c6
+	get_all_dependencies_by_unit(vars->dbus_conn, unit, item, visited_units);
cf36c6
+	oscap_htable_free(visited_units, NULL);
cf36c6
 
cf36c6
 	probe_item_collect(vars->ctx, item);
cf36c6
 	SEXP_free(se_unit);