Validating libfko Memory Usage with Test::Valgrind
26 October, 2013
The fwknop project consistently uses valgrind
to ensure that memory leaks, double free() conditions, and other problems do not creep into the code base.
A high level of automation is built around
valgrind usage with the fwknop test suite, and a
recent addition
extends this even further by using the excellent CPAN
Test::Valgrind module. Even
though the test suite has had the ability to run tests through valgrind, previous to this change these
tests only applied to the fwknop C binaries when executed directly by the test suite. Further, some of the most
rigorous testing is done through the usage of the perl FKO extension to fuzz libfko functions, so
without the Test::Valgrind module these tests also could not take advantage of valgrind support. Now
that the test suite supports Test::Valgrind (and a check is done to see if it is installed), all fuzzing
tests can also be validated with valgrind. Technically, the fuzzing tests have been added as FKO built-in
tests in the t/ directory, and the test suite runs them through Test::Valgrind like this:
# prove --exec 'perl -Iblib/lib -Iblib/arch -MTest::Valgrind' t/*.tHere is a complete example - first, run the test suite like so:
# ./test-fwknop.pl --enable-all --include perl --test-limit 3
[+] Starting the fwknop test suite...
args: --enable-all --include perl --test-limit 3
[+] Total test buckets to execute: 3
[perl FKO module] [compile/install] to: ./FKO...................pass (1)
[perl FKO module] [make test] run built-in tests................pass (2)
[perl FKO module] [prove t/*.t] Test::Valgrind..................pass (3)
[valgrind output] [flagged functions] ..........................pass (4)
Run time: 1.27 minutes
[+] 0/0/0 OpenSSL tests passed/failed/executed
[+] 0/0/0 OpenSSL HMAC tests passed/failed/executed
[+] 4/0/4 test buckets passed/failed/executed
Note that all tests passed as shown above. This indicates that the test suite has not
found any memory leaks through the fuzzing tests run via Test::Valgrind. But, let's
validate this by artificially introducing a memory leak and see if the test suite can
automatically catch it. For example, here is a patch that forces a memory leak in the
validate_access_msg()
libfko function. This function ensures that the shape of the access request conforms to something fwknop
expects like "1.2.3.4,tcp/22". The memory leak happens because a new buffer is allocated
from the heap but is never free()'d before returning from the function (obviously this
patch is for illustration and testing purposes only):
$ git diff
diff --git a/lib/fko_message.c b/lib/fko_message.c
index fa6803b..c04e035 100644
--- a/lib/fko_message.c
+++ b/lib/fko_message.c
@@ -251,6 +251,13 @@ validate_access_msg(const char *msg)
const char *ndx;
int res = FKO_SUCCESS;
int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE);
+ char *leak = NULL;
+
+ leak = malloc(100);
+ leak[0] = 'a';
+ leak[1] = 'a';
+ leak[2] = '\0';
+ printf("LEAK: %s\n", leak);
if(startlen == MAX_SPA_MESSAGE_SIZE)
return(FKO_ERROR_INVALID_DATA_MESSAGE_ACCESS_MISSING);
Now recompile fwknop and run the test suite again, after applying the patch (recompilation
output is not shown):
# cd ../
# make
# test
# ./test-fwknop.pl --enable-all --include perl --test-limit 3
[+] Starting the fwknop test suite...
args: --enable-all --include perl --test-limit 3
Saved results from previous run to: output.last/
Valgrind mode enabled, will import previous coverage from:
output.last/valgrind-coverage/
[+] Total test buckets to execute: 3
[perl FKO module] [compile/install] to: ./FKO...................pass (1)
[perl FKO module] [make test] run built-in tests................pass (2)
[perl FKO module] [prove t/*.t] Test::Valgrind..................fail (3)
[valgrind output] [flagged functions] ..........................fail (4)
Run time: 1.27 minutes
[+] 0/0/0 OpenSSL tests passed/failed/executed
[+] 0/0/0 OpenSSL HMAC tests passed/failed/executed
[+] 2/2/4 test buckets passed/failed/executed
This time two tests fail. The first is the test that runs the perl FKO module built-in
tests under Test::Valgrind, and the second is the "flagged functions" test which compares
test suite output looking for new functions that valgrind has flagged vs. the previous
test suite execution. By looking at the output file of the "flagged functions" test it
is easy to see the offending function where the new memory leak exists. This provides an
easy, automated way of memory leak detection that is driven by perl FKO fuzzing tests.
# cat output/4.test
[+] fwknop client functions (with call line numbers):
10 : validate_access_msg [fko_message.c:256]
6 : fko_set_spa_message [fko_message.c:184]
4 : fko_new_with_data [fko_funcs.c:263]
4 : fko_decrypt_spa_data [fko_encryption.c:264]
4 : fko_decode_spa_data [fko_decode.c:350]
Currently, there are no known memory leaks in the fwknop code, and automation built
around the Test::Valgrind module will help keep it that way.




