mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-12-26 03:16:18 +00:00
PPP, PPPoS: drop input packets much bigger than our MRU
Our current HDLC decoder does not protect against starving the Rx PBUF POOL for one packet, most likely due to received garbage on the serial port. Prevent starving the Rx pool by checking incoming packets length against PPP_MRU with a 10% margin because we only want to avoid filling all PBUFs with garbage, we don't have to be pedantic. Fixes bug #58441: Invalid PPP data accumulates forever.
This commit is contained in:
parent
51c6548631
commit
a39ce0f53b
@ -631,12 +631,37 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l)
|
|||||||
if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) {
|
if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) {
|
||||||
u16_t pbuf_alloc_len;
|
u16_t pbuf_alloc_len;
|
||||||
if (pppos->in_tail != NULL) {
|
if (pppos->in_tail != NULL) {
|
||||||
|
u16_t mru;
|
||||||
pppos->in_tail->tot_len = pppos->in_tail->len;
|
pppos->in_tail->tot_len = pppos->in_tail->len;
|
||||||
if (pppos->in_tail != pppos->in_head) {
|
if (pppos->in_tail != pppos->in_head) {
|
||||||
pbuf_cat(pppos->in_head, pppos->in_tail);
|
pbuf_cat(pppos->in_head, pppos->in_tail);
|
||||||
/* give up the in_tail reference now */
|
/* give up the in_tail reference now */
|
||||||
pppos->in_tail = NULL;
|
pppos->in_tail = NULL;
|
||||||
}
|
}
|
||||||
|
/* Compute MRU including headers length. If smaller packets are
|
||||||
|
* requested, we must still be able to receive packets of the
|
||||||
|
* default MRU for control packets. */
|
||||||
|
mru = LWIP_MAX(PPP_MRU, PPP_DEFMRU)
|
||||||
|
/* Add 10% more. We only want to avoid filling all PBUFs with garbage,
|
||||||
|
* we don't have to be pedantic. */
|
||||||
|
+ LWIP_MAX(PPP_MRU, PPP_DEFMRU)/10
|
||||||
|
#if IP_FORWARD || LWIP_IPV6_FORWARD
|
||||||
|
+ PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN
|
||||||
|
#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
|
||||||
|
#if PPP_INPROC_IRQ_SAFE
|
||||||
|
+ sizeof(struct pppos_input_header)
|
||||||
|
#endif /* PPP_INPROC_IRQ_SAFE */
|
||||||
|
+ sizeof(pppos->in_protocol);
|
||||||
|
if (pppos->in_head->tot_len > mru) {
|
||||||
|
/* Packet too big. Drop the input packet and let the
|
||||||
|
* higher layers deal with it. Continue processing
|
||||||
|
* received characters in case a new packet starts. */
|
||||||
|
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: packet too big, max_len=%d, dropping packet\n", ppp->netif->num, mru));
|
||||||
|
LINK_STATS_INC(link.lenerr);
|
||||||
|
pppos_input_drop(pppos);
|
||||||
|
pppos->in_state = PDIDLE; /* Wait for flag character. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If we haven't started a packet, we need a packet header. */
|
/* If we haven't started a packet, we need a packet header. */
|
||||||
pbuf_alloc_len = 0;
|
pbuf_alloc_len = 0;
|
||||||
@ -653,7 +678,7 @@ pppos_input(ppp_pcb *ppp, u8_t *s, int l)
|
|||||||
if (next_pbuf == NULL) {
|
if (next_pbuf == NULL) {
|
||||||
/* No free buffers. Drop the input packet and let the
|
/* No free buffers. Drop the input packet and let the
|
||||||
* higher layers deal with it. Continue processing
|
* higher layers deal with it. Continue processing
|
||||||
* the received pbuf chain in case a new packet starts. */
|
* received characters in case a new packet starts. */
|
||||||
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num));
|
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num));
|
||||||
LINK_STATS_INC(link.memerr);
|
LINK_STATS_INC(link.memerr);
|
||||||
pppos_input_drop(pppos);
|
pppos_input_drop(pppos);
|
||||||
|
Loading…
Reference in New Issue
Block a user