diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 37c6bb61a..77ec04d95 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -992,6 +992,23 @@ tcp_process(struct tcp_pcb *pcb) case CLOSE_WAIT: /* FALLTHROUGH */ case ESTABLISHED: + #if LIMIT_PAYLOAD_THRESHOLD_ENABLE && (LWIP_SOCKET || LWIP_NETCONN) + /* Security: Gracefully handle RX pool exhaustion to prevent socket application + * deadlock. Drop payload data (but ACK it) when approaching pool limit, reserving + * 2 buffers for critical TCP control messages (SYN, FIN) which have minimal payload, + * are not queued to application layer, and are released within the same ethernet_input + * call. This ensures the stack can process connection state changes under memory + * pressure, preventing resource exhaustion attacks and application hangs. + * NOTE: Only active with Socket/Netconn API where queued payload can cause deadlock. + * NOTE: Assumes statistics are enabled (MEMP_STATS). + * NOTE: Assumes no custom buffer allocation. */ + if (MEMP_STATS_GET(used, MEMP_PBUF_POOL) > MEMP_STATS_GET(max, MEMP_PBUF_POOL) - 2) { + if (tcplen > 0) { + pcb->rcv_nxt += tcplen; + } + return ERR_OK; + } + #endif tcp_receive(pcb); if (recv_flags & TF_GOT_FIN) { /* passive close */ tcp_ack_now(pcb); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 2573285f4..3327a984b 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1455,6 +1455,25 @@ #endif #endif +/** + * LIMIT_PAYLOAD_THRESHOLD_ENABLE: Graceful RX pool exhaustion handling to prevent + * socket application deadlock. + * + * Security: When enabled, prevents resource exhaustion attacks and application hangs + * by dropping incoming payload (while still ACKing it) when PBUF_POOL approaches + * exhaustion. This reserves 2 buffers for critical TCP control messages (SYN, FIN) + * which are released immediately within the same ethernet_input call, ensuring the + * stack can always process connection state changes even under memory pressure. + * + * Only effective with Socket/Netconn API where payload is queued and can cause + * deadlock if the application cannot read due to buffer starvation. + * Requires MEMP_STATS to be enabled for buffer usage tracking. + * Define to 0 to disable this feature. + */ +#if !defined LIMIT_PAYLOAD_THRESHOLD_ENABLE || defined __DOXYGEN__ +#define LIMIT_PAYLOAD_THRESHOLD_ENABLE 0 +#endif + /** * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. */