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;