espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.31k stars 7.36k forks source link

MDNS special packet from Android App crashes and reboots ESP32/ESP32-S2 #6368

Closed avillacis closed 2 years ago

avillacis commented 2 years ago

Board

ESP32, ESP32-S2

Device Description

Issue reproduced on both YUBOX Node (ESP32) and YUBOX One (ESP32-S2)

Hardware Configuration

ESP32 board has inbuilt I2C sensors, otherwise plain ESP32-S2 board has buzzer and I2C sensors on different pins

Version

v2.0.2

IDE Name

Arduino IDE 1.8.19

Operating System

Android 8.x, Android 9

Flash frequency

80 MHz

PSRAM enabled

no

Upload speed

115200

Description

I downloaded an Android App to perform MDNS discovery of various ESP32 and ESP32-S2 devices connected to a local network. The Android App is Service Browser by Andriy Druk. This is the link to the Google Play Store.

My YUBOX Framework projects enable MDNS and expose _http._tcp as a MDNS service in order to be discoverable. With other OS such as Fedora Linux and Windows, all runs OK. However, when using the app, and choosing the _http._tcp section, then the specific ESP32 name exposed by the device, the device itself crashes and reboots.

The below sketch also reproduces this bug. It is a straightforward copy of the MDNS HTTP server example provided by Arduino-ESP32, except with my WiFi credentials, and the MDNS name changed to esp32-crashme.

The expected behavior is, obviously, no crash.

Sketch

#include <Arduino.h>
#include <WiFi.h>
#include <ESPmDNS.h>

static const char * ssid = ".....";
static const char * password = ".....";

// TCP server at port 80 will respond to HTTP requests
WiFiServer server(80);

void setup()
{
    Serial.begin(115200);

    // Connect to WiFi network
    WiFi.begin(ssid, password);
    Serial.println("");

    // Wait for connection
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

    // Set up mDNS responder:
    // - first argument is the domain name, in this example
    //   the fully-qualified domain name is "esp32.local"
    // - second argument is the IP address to advertise
    //   we send our IP address on the WiFi network
    if (!MDNS.begin("esp32-crashme")) {
        Serial.println("Error setting up MDNS responder!");
        while(1) {
            delay(1000);
        }
    }
    Serial.println("mDNS responder started");

    // Start TCP (HTTP) server
    server.begin();
    Serial.println("TCP server started");

    // Add service to MDNS-SD
    MDNS.addService("http", "tcp", 80);
}

void loop()
{
    // Check if a client has connected
    WiFiClient client = server.available();
    if (!client) {
        return;
    }
    Serial.println("");
    Serial.println("New client");

    // Wait for data from client to become available
    while(client.connected() && !client.available()){
        delay(1);
    }

    // Read the first line of HTTP request
    String req = client.readStringUntil('\r');

    // First line of HTTP request looks like "GET /path HTTP/1.1"
    // Retrieve the "/path" part by finding the spaces
    int addr_start = req.indexOf(' ');
    int addr_end = req.indexOf(' ', addr_start + 1);
    if (addr_start == -1 || addr_end == -1) {
        Serial.print("Invalid request: ");
        Serial.println(req);
        return;
    }
    req = req.substring(addr_start + 1, addr_end);
    Serial.print("Request: ");
    Serial.println(req);

    String s;
    if (req == "/")
    {
        IPAddress ip = WiFi.localIP();
        String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP32 at ";
        s += ipStr;
        s += "</html>\r\n\r\n";
        Serial.println("Sending 200");
    }
    else
    {
        s = "HTTP/1.1 404 Not Found\r\n\r\n";
        Serial.println("Sending 404");
    }
    client.print(s);

    client.stop();
    Serial.println("Done with client");
}

Debug Message

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1324
ho 0 tail 12 room 4
load:0x40078000,len:13508
load:0x40080400,len:3604
entry 0x400805f0
[     1][V][WiFiServer.h:42] WiFiServer(): WiFiS�␘����:WiFiServer(port=80, ...)
[     2][D][esp32-hal-cpu.c:211] setCpuFrequencyMhz(): PLL: 480 / 2 = 240 Mhz, APB: 80000000 Hz
[    60][D][WiFiGeneric.cpp:831] _eventCallback(): Arduino Event: 0 - WIFI_READY
[   148][V][WiFiGeneric.cpp:272] _arduino_event_cb(): STA Started
[   149][V][WiFiGeneric.cpp:96] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
[   150][D][WiFiGeneric.cpp:831] _eventCallback(): Arduino Event: 2 - STA_START

....[  2425][V][WiFiGeneric.cpp:284] _arduino_event_cb(): STA Connected: SSID: PSW-DEVICES, BSSID: 46:d9:e7:b7:1a:c2, Channel: 1, Auth: WPA2_PSK
[  2426][D][WiFiGeneric.cpp:831] _eventCallback(): Arduino Event: 4 - STA_CONNECTED
[  2554][V][WiFiGeneric.cpp:294] _arduino_event_cb(): STA Got New IP:172.16.238.40
[  2554][D][WiFiGeneric.cpp:831] _eventCallback(): Arduino Event: 7 - STA_GOT_IP
[  2557][D][WiFiGeneric.cpp:880] _eventCallback(): STA IP: 172.16.238.40, MASK: 255.255.240.0, GW: 172.16.224.1
.
Connected to PSW-DEVICES
IP address: 172.16.238.40
mDNS responder started
TCP server started
Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x4008941f  PS      : 0x00060630  A0      : 0x800fb8d7  A1      : 0x3ffcc020  
A2      : 0x3ffcac90  A3      : 0x00000000  A4      : 0x00000018  A5      : 0x3ffcc3a8  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x0000005f  A9      : 0x00000000  
A10     : 0x00000000  A11     : 0x3ffc4bb2  A12     : 0x3ff96355  A13     : 0x3ffc4b36  
A14     : 0x0000006c  A15     : 0x00000000  SAR     : 0x00000004  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x40089078  LEND    : 0x4008908e  LCOUNT  : 0x00000000  

Backtrace:0x4008941c:0x3ffcc0200x400fb8d4:0x3ffcc040 0x400ff6c1:0x3ffcc070 0x40100361:0x3ffcc140 

----------
PC: 0x4008941f: strcasecmp at /builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/newlib/newlib/libc/string/strcasecmp.c line 46
EXCVADDR: 0x00000000

Decoding stack results
0x4008941c: strcasecmp at /builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/newlib/newlib/libc/string/strcasecmp.c line 46
0x400fb8d4: _mdns_get_service_item_instance at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 265
0x400ff6c1: mdns_parse_packet at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 1461
0x40100361: _mdns_service_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 4460

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

avillacis commented 2 years ago

msdn-capture-esp32-crashme-with-crash.zip This is a zipped PCAP file taken with Wireshark, showing MDNS traffic between the Android phone and the ESP32 device. The IPs are 172.16.238.40 for the ESP32 and 172.16.238.189 for the Android phone. I believe some of these MDNS queries are the cause of the crash.

chegewara commented 2 years ago

https://github.com/espressif/esp-idf/issues/8307

avillacis commented 2 years ago

The previously-mentioned Android App still causes a crash in the ESP32 firmware when compiled under v2.0.3-rc1.

espressif/esp-idf#8307

This espressif/esp-idf issue is marked as "resolved" but apparently the change is still not present in -rc1.

chegewara commented 2 years ago

Its resolved in idf master, not sure if already backported to v4.4, and most likely not included in v2.0.3-rc1.

VojtechBartoska commented 2 years ago

Adding this to roadmap and when we have time we will test this.

Belleson commented 2 years ago

I can confirm this problem using the above sketch and also my ESP32 app. I'm using platformio with configuration

[env:esp32dev] upload_speed = 921600 monitor_speed = 115200 monitor_filters = esp32_exception_decoder platform = https://github.com/platformio/platform-espressif32.git board = esp32dev framework = arduino platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master lib_deps =

Also, the Android Service Browser by Andriy Druk shows the IP and DNS name "esp32-crashme", but a browser (Vivaldi or Opera) will not open the page using http://esp32-crashme.local, while it will open using http://[ip address]

Also a Windows 10 browser does not open the page http://esp32-crashme.local and cannot ping esp32-crashme.local. I have bonjour 64 bit installed. Also checked for zeroconf services using python

>>> from zeroconf import ZeroconfServiceTypes
>>> ZeroconfServiceTypes.find()
()
avillacis commented 2 years ago

Still crashing in the same way when sketch compiled with 2.0.3 stable.

VojtechBartoska commented 2 years ago

Thanks for testing, we will investigate this in next milestone.

me-no-dev commented 2 years ago

I think I got what is going on. Can you please try to add MDNS. addServiceTxt("http", "tcp","hello","world"); after MDNS.addService("http", "tcp", 80);

avillacis commented 2 years ago

I think I got what is going on. Can you please try to add MDNS. addServiceTxt("http", "tcp","hello","world"); after MDNS.addService("http", "tcp", 80);

I just performed this test, not exactly with those strings, but two other ones. Device STILL crashes:

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x40007b47  PS      : 0x00060c30  A0      : 0x800eb7eb  A1      : 0x3ffe2190  
A2      : 0x3ffe2558  A3      : 0x00000000  A4      : 0x0000005f  A5      : 0x3ffe3264  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x80007b41  A9      : 0x00000010  
A10     : 0x3ffac7cb  A11     : 0x00000044  A12     : 0x00000006  A13     : 0x00000000  
A14     : 0x0000006c  A15     : 0x00000000  SAR     : 0x00000019  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x00000006  LEND    : 0x00000000  LCOUNT  : 0x40028031  

Backtrace:0x40007b44:0x3ffe21900x400eb7e8:0x3ffe21b0 0x400ef1e9:0x3ffe21e0 0x400efdc1:0x3ffe22b0 

PC: 0x40007b47
EXCVADDR: 0x00000000

Decoding stack results
0x400eb7e8: _mdns_get_service_item_instance at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 265
0x400ef1e9: mdns_parse_packet at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 1482
0x400efdc1: _mdns_service_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mdns/mdns.c line 4473

In the Android app, the phone managed to retrieve the strings I added as part of the test.

Belleson commented 2 years ago

With this:

    if (!MDNS.begin(hostname))
    {
        Serial.println("Error starting mDNS");
        return;
    }
    MDNS.addService("http", "tcp", 80);
    MDNS.addServiceTxt("http", "tcp", "hello", "world"); 

I do not see the crash any more from Druk Service Browser. Also dns.local is working on Windows 10 browser and ping. YAY! Thanks!

Android (LG G8 phone with Vivaldi and Opera) still works only with IP address but not with dns lookup, even though Service Browser shows mDNS name.

avillacis commented 2 years ago

With this:

  if (!MDNS.begin(hostname))
  {
      Serial.println("Error starting mDNS");
      return;
  }
  MDNS.addService("http", "tcp", 80);
  MDNS.addServiceTxt("http", "tcp", "hello", "world"); 

I do not see the crash any more from Druk Service Browser. Also dns.local is working on Windows 10 browser and ping. YAY! Thanks!

Android (LG G8 phone with Vivaldi and Opera) still works only with IP address but not with dns lookup, even though Service Browser shows mDNS name.

Your experience does not match mine.

I am still experiencing crashes. I used the strings "YUBOX", "xyzxy" instead of "hello", "world". I am using an ESP32S2 with PSRAM enabled and compiled under Arduino-ESP32 v2.3.0. What is your setup?

Belleson commented 2 years ago

Your experience does not match mine.

I am still experiencing crashes. I used the strings "YUBOX", "xyzxy" instead of "hello", "world". I am using an ESP32S2 with PSRAM enabled and compiled under Arduino-ESP32 v2.3.0. What is your setup?

My apology, I was not thorough enough in my test. I thought maybe it was because I had "_http" and not "http" but now I see a crash with either one.

--- Miniterm on COM6 115200,8,N,1 --- --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:1184 load:0x40078000,len:12784 load:0x40080400,len:3032 entry 0x400805e4

Connected to IP address: 192.168.4.1 ENTERING initRadSocket() ENTERING initChannel() ENTERING setRelayAddress()

Input channel: 4 set. Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.

Core 0 register dump: PC : 0x400894b7 PS : 0x00060830 A0 : 0x8010a41b A1 : 0x3ffcd8f0 A2 : 0x3ffcc9e8 A3 : 0x00000000 A4 : 0x8008e99c A5 : 0x3ffcd820
A6 : 0x00000003 A7 : 0x00060023 A8 : 0x0000005f A9 : 0x00000000 A10 : 0x00000000 A11 : 0x003fffff A12 : 0x3ff96355 A13 : 0x3ffcd7f0
A14 : 0x00000001 A15 : 0x3ffccae0 SAR : 0x0000001c EXCCAUSE: 0x0000001c EXCVADDR: 0x00000000 LBEG : 0x4008904c LEND : 0x40089062 LCOUNT : 0x00000000

Backtrace:0x400894b4:0x3ffcd8f00x4010a418:0x3ffcd910 0x4010e20d:0x3ffcd940 0x4010eead:0x3ffcda10

0 0x400894b4:0x3ffcd8f00 in strcasecmp at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/string/strcasecmp.c:46 (discriminator 4)

ELF file SHA256: 0000000000000000

Rebooting... ets Jun 8 2016 00:22:57

me-no-dev commented 2 years ago

yup... my fault misreading the request. It does not contain service name at all and that is what is crashing mdns. It never expected such TXT query. Fix was merged in IDF master here waiting to be backported to 4.4 so that we can pick it up :)

Seref commented 2 years ago

Hi there, I also encountered this problem! I don't really know what the correct way of fixing this issue here on github is (the backporting to 4.4 thing).

To get something that works in the meantime I downloaded arduino-esp32 v2.0.3 and esp-idf v4.4.1 and replaced the mdns folder in components with the one the latest one on the master branch of the esp-idf repo. I used that to generated the necessary libmdns.a file for my project.

If someone else wants to use this in the mean time until a proper fix drops here are the necessary mdns files: https://github.com/Seref/temporary_libmdns_fix_for_arduino-esp32

There are some instructions on how to use it, I only tested this with an ESP32, I used Windows and PlattformIO to test this out, so your mileage may vary.

Note: I will remove the repository when the proper fix is here, also be aware that updates to the package that are loaded automatically may break things since this is just a drag&drop solution, you have to apply this whenever the package gets replaced which can be prevented (atleast as far as I know in PlattformIO) by just specifying the version of the package you want.

Hope this helps 😁

me-no-dev commented 2 years ago

Please try 2.0.4

avillacis commented 2 years ago

I can confirm this bug was FIXED when building under 2.0.4 on both ESP32 and ESP32-S2. Thanks!