Check configuration for internal loops.
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Wed, 17 Sep 2008 10:18:04 +0000 (12:18 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Wed, 17 Sep 2008 10:18:04 +0000 (12:18 +0200)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
postlicyd/config.c
postlicyd/filter.c
postlicyd/filter.h

index d964aaa..20716b2 100644 (file)
@@ -111,6 +111,9 @@ static bool config_second_pass(config_t *config)
     if (!ok) {
         return false;
     }
+    if (!filter_check_safety(&config->filters)) {
+        return false;
+    }
 
     ok = false;
     foreach (filter_param_t *param, config->params) {
index 4bab4c9..a067ef3 100644 (file)
@@ -129,6 +129,42 @@ bool filter_update_references(filter_t *filter, A(filter_t) *filter_list)
     return true;
 }
 
+static inline bool filter_check_loop(filter_t *filter, A(filter_t) *array, bool cleanup)
+{
+    if (cleanup) {
+        foreach (filter_t *filter2, *array) {
+            filter2->seen = false;
+        }}
+    } else if (filter->seen) {
+        return false;
+    }
+    if (filter->safe) {
+        return true;
+    }
+    filter->seen = true;
+    foreach (filter_hook_t *hook, filter->hooks) {
+        if (hook->postfix) {
+            continue;
+        }
+        if (!filter_check_loop(array_ptr(*array, hook->filter_id), array, false)) {
+            return false;
+        }
+    }}
+    filter->safe = true;
+    return true;
+}
+
+bool filter_check_safety(A(filter_t) *array)
+{
+    foreach (filter_t *filter, *array) {
+        if (!filter_check_loop(filter, array, true)) {
+            syslog(LOG_ERR, "the filter tree contains a loop");
+            return false;
+        }
+    }}
+    return true;
+}
+
 void filter_wipe(filter_t *filter)
 {
     filter_destructor_t destructor = destructors[filter->type];
index abfb5af..e8319d3 100644 (file)
@@ -70,10 +70,15 @@ typedef struct filter_t {
     void *data;
 
     A(filter_param_t) params;
+
+    /* Internal: to check the filter tree structure.
+     */
+    unsigned safe   :1;
+    unsigned seen   :1;
 } filter_t;
 ARRAY(filter_t)
 
-#define FILTER_INIT { NULL, FTK_UNKNOWN, ARRAY_INIT, NULL, ARRAY_INIT }
+#define FILTER_INIT { NULL, FTK_UNKNOWN, ARRAY_INIT, NULL, ARRAY_INIT, false, false }
 #define CHECK_FILTER(Filter)                                                   \
     assert(Filter != FTK_UNKNOWN && Filter != FTK_count                        \
            && "Unknown filter type")
@@ -147,6 +152,9 @@ static inline int filter_find_with_name(A(filter_t) *array, const char *name)
 __attribute__((nonnull(1,2)))
 bool filter_update_references(filter_t *filter, A(filter_t) *array);
 
+__attribute__((nonnull(1)))
+bool filter_check_safety(A(filter_t) *array);
+
 __attribute__((nonnull(1)))
 static inline void filter_hook_wipe(filter_hook_t *hook)
 {