diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c index 2f6b59f81..6f276d775 100644 --- a/src/libstrongswan/tests/suites/test_chunk.c +++ b/src/libstrongswan/tests/suites/test_chunk.c @@ -939,6 +939,44 @@ START_TEST(test_chunk_map) } END_TEST +START_TEST(test_chunk_map_clear) +{ + chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05); +#ifdef WIN32 + char *path = "C:\\Windows\\Temp\\strongswan-chunk-map-test"; +#else + char *path = "/tmp/strongswan-chunk-map-clear-test"; +#endif + + ck_assert(chunk_write(contents, path, 022, TRUE)); + + /* read */ + map = chunk_map(path, FALSE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + ck_assert(chunk_unmap_clear(map)); + /* we can't verify that clearing worked as we don't have access to the + * memory anymore and mmap with MAP_ANONYMOUS | MAP_UNINITIALIZED of the + * same area will only work if the kernel allows this */ + + /* write */ + map = chunk_map(path, TRUE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + map->ptr[0] = 0x42; + ck_assert(chunk_unmap_clear(map)); + + /* verify write */ + contents.ptr[0] = 0x42; + map = chunk_map(path, FALSE); + ck_assert(map != NULL); + ck_assert_msg(chunk_equals(*map, contents), "%B", map); + ck_assert(chunk_unmap_clear(map)); + + unlink(path); +} +END_TEST + /******************************************************************************* * test for chunk_from_fd */ @@ -1144,6 +1182,7 @@ Suite *chunk_suite_create() tc = tcase_create("chunk_map"); tcase_add_test(tc, test_chunk_map); + tcase_add_test(tc, test_chunk_map_clear); suite_add_tcase(s, tc); tc = tcase_create("chunk_from_fd"); diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index ac19fafb4..dd4a0a034 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -396,9 +396,9 @@ chunk_t *chunk_map(char *path, bool wr) } /** - * See header. + * Unmap the given chunk and optionally clear it */ -bool chunk_unmap(chunk_t *public) +static bool chunk_unmap_internal(chunk_t *public, bool clear) { mmaped_chunk_t *chunk; bool ret = FALSE; @@ -408,6 +408,10 @@ bool chunk_unmap(chunk_t *public) #ifdef HAVE_MMAP if (chunk->map && chunk->map != MAP_FAILED) { + if (!chunk->wr && clear) + { + memwipe(chunk->map, chunk->len); + } ret = munmap(chunk->map, chunk->len) == 0; tmp = errno; } @@ -436,6 +440,10 @@ bool chunk_unmap(chunk_t *public) { ret = TRUE; } + if (clear) + { + memwipe(chunk->map, chunk->len); + } free(chunk->map); #endif /* !HAVE_MMAP */ close(chunk->fd); @@ -445,6 +453,22 @@ bool chunk_unmap(chunk_t *public) return ret; } +/* + * Described in header + */ +bool chunk_unmap(chunk_t *public) +{ + return chunk_unmap_internal(public, FALSE); +} + +/* + * Described in header + */ +bool chunk_unmap_clear(chunk_t *public) +{ + return chunk_unmap_internal(public, TRUE); +} + /** hex conversion digits */ static char hexdig_upper[] = "0123456789ABCDEF"; static char hexdig_lower[] = "0123456789abcdef"; diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index a5eb5ed3b..6cf6510ca 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -114,7 +114,7 @@ bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force); bool chunk_from_fd(int fd, chunk_t *chunk); /** - * mmap() a file to a chunk + * mmap() a file to a chunk. * * The returned chunk structure is allocated from heap, but it must be freed * through chunk_unmap(). A user may alter the chunk ptr or len, but must pass @@ -129,16 +129,29 @@ bool chunk_from_fd(int fd, chunk_t *chunk); chunk_t *chunk_map(char *path, bool wr); /** - * munmap() a chunk previously mapped with chunk_map() + * munmap() a chunk previously mapped with chunk_map(). * * When unmapping a writeable map, the return value should be checked to * ensure changes landed on disk. * * @param chunk pointer returned from chunk_map() - * @return TRUE of changes written back to file + * @return TRUE if changes written back to file */ bool chunk_unmap(chunk_t *chunk); +/** + * munmap() a chunk previously mapped with chunk_map() after clearing it. + * + * @note Writable maps (i.e. created with wr = TRUE) are NOT cleared. + * + * When unmapping a writeable map, the return value should be checked to + * ensure changes landed on disk. + * + * @param chunk pointer returned from chunk_map() + * @return TRUE if changes written back to file + */ +bool chunk_unmap_clear(chunk_t *chunk); + /** * Convert a chunk of data to hex encoding. *