diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c
index 5fe1729a..554b625f 100644
--- a/checkpolicy/module_compiler.c
+++ b/checkpolicy/module_compiler.c
@@ -761,20 +761,18 @@ int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
 	return 0;
 }
 
-static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	if (key)
 		free(key);
 	free(datum);
-	return 0;
 }
 
 static void class_datum_destroy(class_datum_t * cladatum)
 {
 	if (cladatum != NULL) {
-		hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
-		hashtab_destroy(cladatum->permissions.table);
+		hashtab_destroy(cladatum->permissions.table, perm_destroy, NULL);
 		free(cladatum);
 	}
 }
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index ea0cef32..8aa305c9 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1984,13 +1984,11 @@ exit:
 	return rc;
 }
 
-static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
+static void __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
 {
 	free(k);
 	ebitmap_destroy(datum);
 	free(datum);
-
-	return SEPOL_OK;
 }
 
 static int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
@@ -5230,9 +5228,8 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
 	rc = SEPOL_OK;
 
 exit:
-	hashtab_destroy(role_trans_table);
-	hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
-	hashtab_destroy(avrulex_ioctl_table);
+	hashtab_destroy(role_trans_table, NULL, NULL);
+	hashtab_destroy(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
 	free(type_value_to_cil);
 	free(class_value_to_cil);
 	if (perm_value_to_cil != NULL) {
diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c
index e32ee4e9..18ecfe87 100644
--- a/libsepol/cil/src/cil_strpool.c
+++ b/libsepol/cil/src/cil_strpool.c
@@ -87,12 +87,11 @@ char *cil_strpool_add(const char *str)
 	return strpool_ref->str;
 }
 
-static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused)))
+static void cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused)))
 {
 	struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry*)d;
 	free(strpool_ref->str);
 	free(strpool_ref);
-	return SEPOL_OK;
 }
 
 void cil_strpool_init(void)
@@ -115,8 +114,7 @@ void cil_strpool_destroy(void)
 	pthread_mutex_lock(&cil_strpool_mutex);
 	cil_strpool_readers--;
 	if (cil_strpool_readers == 0) {
-		hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL);
-		hashtab_destroy(cil_strpool_tab);
+		hashtab_destroy(cil_strpool_tab, cil_strpool_entry_destroy, NULL);
 		cil_strpool_tab = NULL;
 	}
 	pthread_mutex_unlock(&cil_strpool_mutex);
diff --git a/libsepol/cil/src/cil_symtab.c b/libsepol/cil/src/cil_symtab.c
index 7e43a690..73cdd734 100644
--- a/libsepol/cil/src/cil_symtab.c
+++ b/libsepol/cil/src/cil_symtab.c
@@ -133,18 +133,16 @@ int cil_symtab_map(symtab_t *symtab,
 	return hashtab_map(symtab->table, apply, args);
 }
 
-static int __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, __attribute__((unused)) void *args)
+static void __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, __attribute__((unused)) void *args)
 {
 	struct cil_symtab_datum *datum = d;
 	datum->symtab = NULL;
-	return SEPOL_OK;
 }
 
 void cil_symtab_destroy(symtab_t *symtab)
 {
 	if (symtab->table != NULL){
-		cil_symtab_map(symtab, __cil_symtab_destroy_helper, NULL);
-		hashtab_destroy(symtab->table);
+		hashtab_destroy(symtab->table, __cil_symtab_destroy_helper, NULL);
 		symtab->table = NULL;
 	}
 }
diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h
index 5318ea19..9b19946b 100644
--- a/libsepol/include/sepol/policydb/conditional.h
+++ b/libsepol/include/sepol/policydb/conditional.h
@@ -127,7 +127,7 @@ extern void cond_policydb_destroy(policydb_t * p);
 extern void cond_list_destroy(cond_list_t * list);
 
 extern int cond_init_bool_indexes(policydb_t * p);
-extern int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p);
+extern void cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p);
 
 extern int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum,
 			   void *datap);
diff --git a/libsepol/include/sepol/policydb/hashtab.h b/libsepol/include/sepol/policydb/hashtab.h
index 354ebb43..7aa88f3b 100644
--- a/libsepol/include/sepol/policydb/hashtab.h
+++ b/libsepol/include/sepol/policydb/hashtab.h
@@ -89,8 +89,14 @@ extern hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t k);
 
 /*
    Destroys the specified hash table.
+   Applies the specified destroy function to (key,datum,args) for
+   all entries.
+
  */
-extern void hashtab_destroy(hashtab_t h);
+extern void hashtab_destroy(hashtab_t h,
+			    void (*destroy) (hashtab_key_t k,
+					    hashtab_datum_t d,
+					    void *args), void *args);
 
 /*
    Applies the specified apply function to (key,datum,args)
diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 48b7b8bb..8cf82da6 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -634,7 +634,7 @@ extern int policydb_context_isvalid(const policydb_t * p,
 				    const context_struct_t * c);
 
 extern void symtabs_destroy(symtab_t * symtab);
-extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
+extern void scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
 
 extern void class_perm_node_init(class_perm_node_t * x);
 extern void type_set_init(type_set_t * x);
diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c
index 7900e928..b51639d4 100644
--- a/libsepol/src/conditional.c
+++ b/libsepol/src/conditional.c
@@ -528,13 +528,12 @@ int cond_init_bool_indexes(policydb_t * p)
 	return 0;
 }
 
-int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
+void cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
 		      __attribute__ ((unused)))
 {
 	if (key)
 		free(key);
 	free(datum);
-	return 0;
 }
 
 int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
diff --git a/libsepol/src/hashtab.c b/libsepol/src/hashtab.c
index 922a8a4a..7f3dd00b 100644
--- a/libsepol/src/hashtab.c
+++ b/libsepol/src/hashtab.c
@@ -193,7 +193,10 @@ hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key)
 	return cur->datum;
 }
 
-void hashtab_destroy(hashtab_t h)
+void hashtab_destroy(hashtab_t h,
+		     void (*destroy) (hashtab_key_t k,
+				      hashtab_datum_t d,
+				      void *args), void *args)
 {
 	unsigned int i;
 	hashtab_ptr_t cur, temp;
@@ -206,6 +209,8 @@ void hashtab_destroy(hashtab_t h)
 		while (cur != NULL) {
 			temp = cur;
 			cur = cur->next;
+			if (destroy)
+				destroy(temp->key, temp->datum, args);
 			free(temp);
 		}
 		h->htable[i] = NULL;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 552eb77a..f443ea88 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -895,10 +895,10 @@ int policydb_init(policydb_t * p)
 
 	return 0;
 err:
-	hashtab_destroy(p->range_tr);
+	hashtab_destroy(p->range_tr, NULL, NULL);
 	for (i = 0; i < SYM_NUM; i++) {
-		hashtab_destroy(p->symtab[i].table);
-		hashtab_destroy(p->scope[i].table);
+		hashtab_destroy(p->symtab[i].table, NULL, NULL);
+		hashtab_destroy(p->scope[i].table, NULL, NULL);
 	}
 	avrule_block_list_destroy(p->global);
 	return rc;
@@ -1264,16 +1264,15 @@ int policydb_index_others(sepol_handle_t * handle,
  * symbol data in the policy database.
  */
 
-static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	if (key)
 		free(key);
 	free(datum);
-	return 0;
 }
 
-static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			  __attribute__ ((unused)))
 {
 	common_datum_t *comdatum;
@@ -1281,13 +1280,11 @@ static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 	if (key)
 		free(key);
 	comdatum = (common_datum_t *) datum;
-	(void)hashtab_map(comdatum->permissions.table, perm_destroy, 0);
-	hashtab_destroy(comdatum->permissions.table);
+	hashtab_destroy(comdatum->permissions.table, perm_destroy, NULL);
 	free(datum);
-	return 0;
 }
 
-static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			 __attribute__ ((unused)))
 {
 	class_datum_t *cladatum;
@@ -1297,10 +1294,9 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 		free(key);
 	cladatum = (class_datum_t *) datum;
 	if (cladatum == NULL) {
-		return 0;
+		return;
 	}
-	(void)hashtab_map(cladatum->permissions.table, perm_destroy, 0);
-	hashtab_destroy(cladatum->permissions.table);
+	hashtab_destroy(cladatum->permissions.table, perm_destroy, NULL);
 	constraint = cladatum->constraints;
 	while (constraint) {
 		constraint_expr_destroy(constraint->expr);
@@ -1320,37 +1316,33 @@ static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 	if (cladatum->comkey)
 		free(cladatum->comkey);
 	free(datum);
-	return 0;
 }
 
-static int role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	free(key);
 	role_datum_destroy((role_datum_t *) datum);
 	free(datum);
-	return 0;
 }
 
-static int type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	free(key);
 	type_datum_destroy((type_datum_t *) datum);
 	free(datum);
-	return 0;
 }
 
-static int user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	free(key);
 	user_datum_destroy((user_datum_t *) datum);
 	free(datum);
-	return 0;
 }
 
-static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 			__attribute__ ((unused)))
 {
 	level_datum_t *levdatum;
@@ -1362,25 +1354,23 @@ static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 	free(levdatum->level);
 	level_datum_destroy(levdatum);
 	free(levdatum);
-	return 0;
 }
 
-static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+static void cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 		       __attribute__ ((unused)))
 {
 	if (key)
 		free(key);
 	cat_datum_destroy((cat_datum_t *) datum);
 	free(datum);
-	return 0;
 }
 
-static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
+static void (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
 				  void *datap) = {
 common_destroy, class_destroy, role_destroy, type_destroy, user_destroy,
 	    cond_destroy_bool, sens_destroy, cat_destroy,};
 
-static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
+static void range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
 			    void *p __attribute__ ((unused)))
 {
 	struct mls_range *rt = (struct mls_range *)datum;
@@ -1388,7 +1378,6 @@ static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum,
 	ebitmap_destroy(&rt->level[0].cat);
 	ebitmap_destroy(&rt->level[1].cat);
 	free(datum);
-	return 0;
 }
 
 static void ocontext_selinux_free(ocontext_t **ocontexts)
@@ -1468,8 +1457,7 @@ void policydb_destroy(policydb_t * p)
 	free(p->decl_val_to_struct);
 
 	for (i = 0; i < SYM_NUM; i++) {
-		(void)hashtab_map(p->scope[i].table, scope_destroy, 0);
-		hashtab_destroy(p->scope[i].table);
+		hashtab_destroy(p->scope[i].table, scope_destroy, NULL);
 	}
 	avrule_block_list_destroy(p->global);
 	free(p->name);
@@ -1515,8 +1503,7 @@ void policydb_destroy(policydb_t * p)
 	if (lra)
 		free(lra);
 
-	hashtab_map(p->range_tr, range_tr_destroy, NULL);
-	hashtab_destroy(p->range_tr);
+	hashtab_destroy(p->range_tr, range_tr_destroy, NULL);
 
 	if (p->type_attr_map) {
 		for (i = 0; i < p->p_types.nprim; i++) {
@@ -1539,12 +1526,11 @@ void symtabs_destroy(symtab_t * symtab)
 {
 	int i;
 	for (i = 0; i < SYM_NUM; i++) {
-		(void)hashtab_map(symtab[i].table, destroy_f[i], 0);
-		hashtab_destroy(symtab[i].table);
+		hashtab_destroy(symtab[i].table, destroy_f[i], NULL);
 	}
 }
 
-int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
+void scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 		  __attribute__ ((unused)))
 {
 	scope_datum_t *cur = (scope_datum_t *) datum;
@@ -1553,7 +1539,6 @@ int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
 		free(cur->decl_ids);
 	}
 	free(cur);
-	return 0;
 }
 
 /*
diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c
index a6061851..3430bfc0 100644
--- a/libsepol/src/symtab.c
+++ b/libsepol/src/symtab.c
@@ -51,7 +51,6 @@ void symtab_destroy(symtab_t * s)
 	if (!s)
 		return;
 	if (s->table)
-		hashtab_destroy(s->table);
-	return;
+		hashtab_destroy(s->table, NULL, NULL);
 }
 /* FLASK */
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index f0ed9e33..2eb08bb7 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -539,7 +539,7 @@ static int filenametr_cmp(hashtab_t h __attribute__ ((unused)),
 	return strcmp(ft1->name, ft2->name);
 }
 
-static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum,
+static void filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum,
 			      void *p __attribute__ ((unused)))
 {
 	filenametr_key_t *ft = (filenametr_key_t *)key;
@@ -553,7 +553,6 @@ static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum,
 		free(fd);
 		fd = next;
 	} while (fd);
-	return 0;
 }
 
 typedef struct {
@@ -778,8 +777,7 @@ static int avtab_filename_trans_write(policydb_t *pol, avtab_t *a,
 
 out:
 	/* destroy temp filename transitions table */
-	hashtab_map(fnts_tab, filenametr_destroy, NULL);
-	hashtab_destroy(fnts_tab);
+	hashtab_destroy(fnts_tab, filenametr_destroy, NULL);
 
 	return rc ? -1 : 0;
 }
