BUG/MINOR: acl: remove patterns from the tree before freeing them

A call to free_pattern_tree() upon exit() is made to free all ACL
patterns allocated in a tree (strings or IP addresses). Unfortunately
it happens that this function has been bogus from the beginning, it
walks over the whole tree, frees the nodes but forgets to remove them
from the tree prior to freeing them. So after visiting a leaf, the
next eb_next() call will require to revisit some of the upper nodes
that were just freed. This can remain unnoticed for a long time because
free() often just marks the area as free. But in cases of aggressive
memory freeing, the location will not be mapped anymore and the process
segfaults.

Note that the bug has no impact other than polluting kernel logs and
frightening sysadmins, since it happens just before exit().

Simply adding the debug code below makes it easier to reproduce the
same bug :

	while (node) {
		next = eb_next(node);
+		node->node_p = (void *)-1;
		free(node);
		node = next;
	}

Many thanks to the StackExchange team for their very detailed bug report
that permitted to quickly understand this non-obvious bug!

This fix should be backported to 1.4 which introduced the bug.
This commit is contained in:
Willy Tarreau 2013-11-14 16:00:12 +01:00
parent c08057cc3f
commit 60eccc1841
1 changed files with 1 additions and 0 deletions

View File

@ -871,6 +871,7 @@ static void free_pattern_tree(struct eb_root *root)
node = eb_first(root);
while (node) {
next = eb_next(node);
eb_delete(node);
free(node);
node = next;
}