Files
c5-project/ESP32-C5-Toolkit/FIRMWARE_BUG_REVIEW.md
2026-05-03 23:19:51 -07:00

11 KiB

ESP32-C5 Toolkit Firmware Bug Review & Fixes

Date: 2024
Reviewer: AI Code Review
Firmware Version: 2.0

Executive Summary

Comprehensive review of ESP32-C5 Toolkit firmware identified 10 critical bugs, 5 medium-severity issues, and several improvements. The bugs range from memory leaks and race conditions to deadlock vulnerabilities and unsafe task management.


🔴 CRITICAL BUGS (Must Fix)

1. MUTEX DEADLOCK in frame_analyzer.c

File: main/frame_analyzer.c:57-59
Severity: CRITICAL
Issue: Deadlock when frame_analyzer_capture_start() calls frame_analyzer_reset() while already holding the mutex.

// BUG: frame_analyzer_capture_start takes mutex, then calls reset which tries to take it again
void frame_analyzer_capture_start(...) {
    if (analyzer_mutex && xSemaphoreTake(analyzer_mutex, portMAX_DELAY)) {
        frame_analyzer_reset();  // ❌ This tries to take the same mutex again!
        // ...
    }
}

Fix: Extract reset logic to a non-mutex-protected internal function, or remove mutex from reset when called internally.


2. UNSAFE TASK DELETION - Multiple Locations

Files:

  • main/wifi_sniffer.c:203
  • main/deauth_engine.c:265
  • main/handshake_capture.c:249, 431, 436

Severity: CRITICAL
Issue: vTaskDelete() called directly on potentially running tasks, which can corrupt task structures and cause crashes.

ESP-IDF Best Practice: Tasks should be gracefully stopped (set flag, wait for exit), or suspended before deletion.

Example Bug:

// wifi_sniffer.c:203
if (channel_hopper_task_handle != NULL) {
    vTaskDelete(channel_hopper_task_handle);  // ❌ Unsafe - task may be executing
    channel_hopper_task_handle = NULL;
}

Fix: Suspend task first, then delete:

if (channel_hopper_task_handle != NULL) {
    vTaskSuspend(channel_hopper_task_handle);
    vTaskDelay(pdMS_TO_TICKS(10));  // Allow task to reach safe point
    vTaskDelete(channel_hopper_task_handle);
    channel_hopper_task_handle = NULL;
}

3. MEMORY LEAK in wifi_sniffer.c

File: main/wifi_sniffer.c:144-149
Severity: CRITICAL
Issue: Allocated channel_param memory leaked if xTaskCreate() fails.

uint8_t *channel_param = malloc(sizeof(uint8_t));
if (channel_param) {
    *channel_param = channel;
    xTaskCreate(single_channel_retry_task, "channel_retry", 2048, channel_param, 5, &channel_hopper_task_handle);
    // ❌ If xTaskCreate fails, channel_param is leaked!
}

Fix: Check return value and free on failure:

uint8_t *channel_param = malloc(sizeof(uint8_t));
if (channel_param) {
    *channel_param = channel;
    BaseType_t ret = xTaskCreate(single_channel_retry_task, "channel_retry", 2048, channel_param, 5, &channel_hopper_task_handle);
    if (ret != pdPASS) {
        free(channel_param);  // ✅ Free if task creation fails
    }
}

4. RACE CONDITION in Task Handle Check

Files:

  • main/deauth_engine.c:258-265
  • main/handshake_capture.c:430-437

Severity: CRITICAL
Issue: Task handle checked and then deleted in separate operations, allowing race condition.

// deauth_engine.c:258-265
while (attack_task_handle != NULL && wait_count < 50) {
    vTaskDelay(pdMS_TO_TICKS(100));
    wait_count++;
}

if (attack_task_handle != NULL) {  // ❌ Race: handle could become NULL between check and delete
    vTaskDelete(attack_task_handle);
    attack_task_handle = NULL;
}

Fix: Store handle in local variable atomically:

TaskHandle_t task_to_delete = NULL;
if (xSemaphoreTake(attack_mutex, portMAX_DELAY) == pdTRUE) {
    task_to_delete = attack_task_handle;
    attack_task_handle = NULL;  // Clear while holding mutex
    xSemaphoreGive(attack_mutex);
}

if (task_to_delete != NULL) {
    vTaskSuspend(task_to_delete);
    vTaskDelay(pdMS_TO_TICKS(10));
    vTaskDelete(task_to_delete);
}

5. PCAP BUFFER MEMORY EXHAUSTION

File: main/pcap_serializer.c:84-89
Severity: CRITICAL
Issue: No size limit on PCAP buffer growth - can exhaust all available heap.

// pcap_serializer.c:84
unsigned new_size = pcap_size + sizeof(pcap_record_header_t) + size;
uint8_t *new_buffer = realloc(pcap_buffer, new_size);
if (!new_buffer) {
    ESP_LOGE(TAG, "Failed to reallocate PCAP buffer! PCAP may be incomplete.");
    return;  // ❌ No recovery, buffer left in inconsistent state
}

Fix: Add maximum size limit and better error handling:

#define MAX_PCAP_SIZE (512 * 1024)  // 512KB limit

unsigned new_size = pcap_size + sizeof(pcap_record_header_t) + size;
if (new_size > MAX_PCAP_SIZE) {
    ESP_LOGW(TAG, "PCAP buffer limit reached (%u bytes), dropping frame", MAX_PCAP_SIZE);
    return;
}

uint8_t *new_buffer = realloc(pcap_buffer, new_size);
if (!new_buffer) {
    ESP_LOGE(TAG, "Failed to reallocate PCAP buffer");
    // Optionally: discard oldest packets to free space
    return;
}

6. MISSING ERROR CHECK on Task Creation

File: main/deauth_engine.c:228
Severity: CRITICAL
Issue: xTaskCreate() return value not checked - task may not have been created.

xTaskCreate(dual_band_attack_task, "dual_attack", 8192, NULL, 5, &attack_task_handle);
// ❌ No error check - attack_running is true but task may not exist

Fix: Check return value:

BaseType_t ret = xTaskCreate(dual_band_attack_task, "dual_attack", 8192, NULL, 5, &attack_task_handle);
if (ret != pdPASS) {
    ESP_LOGE(TAG, "Failed to create attack task");
    attack_running = false;
    xSemaphoreGive(attack_mutex);
    return false;
}

7. WiFi MODE CHANGE CONFLICTS

Files: Multiple files change WiFi mode without coordination
Severity: HIGH
Issue: Multiple components (sniffer, deauth, handshake capture) change WiFi mode independently, causing conflicts.

Locations:

  • wifi_sniffer.c:98 - Sets WIFI_MODE_APSTA
  • deauth_engine.c:95, 115 - Sets WIFI_MODE_APSTA, then WIFI_MODE_STA
  • handshake_capture.c:182, 268, 379, 451 - Multiple mode changes

Fix: Implement WiFi mode manager with reference counting:

// Add to wifi_init.c or new wifi_manager.c
static int wifi_mode_ref_count = 0;
static SemaphoreHandle_t wifi_mode_mutex = NULL;

esp_err_t wifi_request_mode(wifi_mode_t requested_mode) {
    if (wifi_mode_mutex == NULL) {
        wifi_mode_mutex = xSemaphoreCreateMutex();
    }
    
    if (xSemaphoreTake(wifi_mode_mutex, portMAX_DELAY) != pdTRUE) {
        return ESP_FAIL;
    }
    
    wifi_mode_ref_count++;
    esp_err_t ret = esp_wifi_set_mode(requested_mode);
    
    xSemaphoreGive(wifi_mode_mutex);
    return ret;
}

void wifi_release_mode(void) {
    if (xSemaphoreTake(wifi_mode_mutex, portMAX_DELAY) == pdTRUE) {
        wifi_mode_ref_count--;
        if (wifi_mode_ref_count <= 0) {
            esp_wifi_set_mode(WIFI_MODE_APSTA);  // Restore default
            wifi_mode_ref_count = 0;
        }
        xSemaphoreGive(wifi_mode_mutex);
    }
}

8. CHANNEL SWITCHING RACE CONDITIONS

File: main/wifi_sniffer.c, main/deauth_engine.c
Severity: HIGH
Issue: Multiple tasks/operations switch channels without coordination.

Example:

  • Channel hopper task continuously changes channel
  • Deauth engine changes channel for attacks
  • Handshake capture sets specific channel

Fix: Implement channel lock mechanism or serialize channel operations.


9. BUFFER OVERFLOW RISK in Frame Analyzer

File: main/frame_analyzer.c:235
Severity: HIGH
Issue: EAPOL packet size not validated before memcpy.

uint16_t eapol_len = sizeof(eapol_packet_header_t) + ntohs(eapol->header.packet_body_length);
if (eapol_len <= sizeof(captured_handshake.eapol)) {
    memcpy(captured_handshake.eapol, eapol, eapol_len);  // ⚠️ Should also check against actual frame size
}

Fix: Add bounds checking against actual received frame size.


10. MISSING NULL CHECK before Memory Free

File: main/web_server.c:1759
Severity: MEDIUM
Issue: Packet freed without null check (though malloc failure is handled).

free(pkt);  // pkt comes from malloc, should be checked

Fix: Add defensive check (though malloc failure is already handled, this is defensive):

if (pkt) {
    free(pkt);
}

🟡 MEDIUM SEVERITY ISSUES

11. Inefficient RSSI Averaging

File: main/signal_analysis.c:46
Issue: Simple average overwrites previous value instead of maintaining running average.

ch->rssi = (ch->rssi + rssi) / 2;  // Loses history

Fix: Use exponential moving average or maintain proper average with count.


12. Hardcoded Credentials in Code

File: Multiple files
Issue: WiFi AP credentials hardcoded ("ESP32-C5-Toolkit", "h4ck3rm4n").

Fix: Store in NVS or use configuration structure.


13. No Timeout on Mutex Operations

Files: Multiple
Issue: Many portMAX_DELAY timeouts - can hang forever if deadlock occurs.

Fix: Use reasonable timeouts and handle timeout errors gracefully.


14. Missing WiFi Error Handling

Files: Multiple
Issue: Several esp_wifi_set_channel() calls don't check return values.

Example: deauth_engine.c:68, handshake_capture.c:389


15. Stack Size May Be Insufficient

Files: Task creation calls
Issue: Some tasks use 2048-8192 bytes stack - may overflow with deep call stacks.

Fix: Monitor stack usage with uxTaskGetStackHighWaterMark() and adjust.


  1. Add Heap Monitoring: Use esp_get_minimum_free_heap_size() to detect memory leaks
  2. Add Watchdog: Implement task watchdog to detect hung tasks
  3. Improve Logging: Add more detailed error context to log messages
  4. Add Unit Tests: Critical path functions should have unit tests
  5. Documentation: Add function-level documentation for all public APIs
  6. Error Recovery: Implement better error recovery mechanisms (e.g., PCAP buffer full)
  7. Resource Limits: Add configurable limits for packet queues, PCAP size, etc.

🔧 PRIORITY FIX ORDER

  1. IMMEDIATE: Fix mutex deadlock (#1)
  2. IMMEDIATE: Fix unsafe task deletions (#2)
  3. HIGH: Fix memory leaks (#3)
  4. HIGH: Add PCAP size limits (#5)
  5. MEDIUM: Implement WiFi mode manager (#7)
  6. MEDIUM: Fix channel switching coordination (#8)
  7. LOW: Address other improvements

📝 NOTES

  • All fixes should be tested on actual hardware
  • Consider adding CONFIG options for buffer sizes
  • Review ESP-IDF v6.0 migration guide for deprecated APIs
  • Some "bugs" may be intentional for performance - verify before changing

REFERENCES

  • ESP-IDF Programming Guide v6.0
  • FreeRTOS Task Management Best Practices
  • ESP32-C5 Technical Reference Manual