busybox
The pointer 'ch' is referenced after being freed if FEATURE_CLEAN_UP is enabled. If FEATURE_CLEAN_UP is defined, then delete_eth_table() frees the previously allocated memory for the pointer 'ch'. However, after that (in a for loop), a statement 'ch->next' dereferences already freed memory.
Bug fixed by commit bc0ffc0e971
Type | UseAfterFree |
Config | FEATURE_CLEAN_UP (1st degree) |
C-features | Structs |
Fix-in | code |
Location | networking/ |
#include <stdio.h> #include <stdlib.h> #include <string.h> #define IFNAMSIZ 16 typedef struct ethtable_s { struct ethtable_s *next; char *ifname; } ethtable_t; #ifdef ENABLE_FEATURE_CLEAN_UP static void delete_eth_table(ethtable_t *ch) { free(ch->ifname); free(ch); }; #else void delete_eth_table(ethtable_t *ch) { } #endif static void prepend_new_eth_table(ethtable_t **clist, char *ifname) { ethtable_t *ch; if (strlen(ifname) >= IFNAMSIZ) printf("interface name '%s' too long", ifname); ch = malloc(sizeof(*ch)); ch->ifname = ifname; ch->next = *clist; *clist = ch; } int main(int argc, char** argv) { ethtable_t *clist = NULL; ethtable_t *ch; prepend_new_eth_table(&clist, argv[0]); #ifdef ENABLE_FEATURE_CLEAN_UP for (ch = clist; ch; ch = ch->next) // ERROR delete_eth_table(ch); #endif return 0; }
diff --git a/simple/bc0ffc0.c b/simple/bc0ffc0.c --- a/simple/bc0ffc0.c +++ b/simple/bc0ffc0.c @@ -39,8 +39,11 @@ prepend_new_eth_table(&clist, argv[0]); #ifdef ENABLE_FEATURE_CLEAN_UP - for (ch = clist; ch; ch = ch->next) // ERROR + ethtable_t *next; + for (ch = clist; ch; ch = next) { // ERROR + next = ch->next; delete_eth_table(ch); + } #endif return 0; } \ No newline at end of file
#include <stdio.h> #include <stdlib.h> #include <string.h> #define IFNAMSIZ 16 typedef struct ethtable_s { struct ethtable_s *next; char *ifname; } ethtable_t; int main(int argc, char** argv) { ethtable_t *clist = NULL; ethtable_t *ch; // prepend_new_eth_table(&clist, argv[0]); if (strlen(ifname) >= IFNAMSIZ) printf("interface name '%s' too long", ifname); ch = malloc(sizeof(*ch)); ch->ifname = ifname; ch->next = *clist; *clist = ch; #ifdef ENABLE_FEATURE_CLEAN_UP for (ch = clist; ch; ch = ch->next) { // ERROR // delete_eth_table(ch); free(ch->ifname); free(ch); } #else #endif return 0; }
. call networking/nameif.c:240:prepend_new_eth_table() .. 194:ch = xzalloc(sizeof(*ch)); . [FEATURE_CLEAN_UP] call networking/nameif.c:319:delete_eth_table() .. [FEATURE_CLEAN_UP] 212:free(ch); . ERROR [FEATURE_CLEAN_UP] 318:ch = ch->next;