fixed bug #43173, pppos_input() corrupts memory if IP_FORWARD is enabled

This commit is contained in:
Simon Goldschmidt 2014-10-12 18:23:10 +02:00 committed by Sylvain Rochet
parent b8d798158b
commit ab9feb2e35

View File

@ -1622,6 +1622,10 @@ pppos_input(ppp_pcb *pcb, u_char *s, int l)
/* Packet consumed, release our references. */
pcrx->in_head = NULL;
pcrx->in_tail = NULL;
#if IP_FORWARD || LWIP_IPV6_FORWARD
/* hide the room for Ethernet forwarding header */
pbuf_header(inp, -(s16_t)PBUF_LINK_HLEN);
#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
#if PPP_INPROC_MULTITHREADED
if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) {
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", pcb->num));
@ -1711,6 +1715,7 @@ pppos_input(ppp_pcb *pcb, u_char *s, int l)
case PDDATA: /* Process data byte. */
/* Make space to receive processed data. */
if (pcrx->in_tail == NULL || pcrx->in_tail->len == PBUF_POOL_BUFSIZE) {
u16_t pbuf_alloc_len;
if (pcrx->in_tail != NULL) {
pcrx->in_tail->tot_len = pcrx->in_tail->len;
if (pcrx->in_tail != pcrx->in_head) {
@ -1720,45 +1725,35 @@ pppos_input(ppp_pcb *pcb, u_char *s, int l)
}
}
/* If we haven't started a packet, we need a packet header. */
pbuf_alloc_len = 0;
#if IP_FORWARD || LWIP_IPV6_FORWARD
/* If IP forwarding is enabled we are using a PBUF_LINK packet type so
/* If IP forwarding is enabled we are reserving PBUF_LINK_HLEN bytes so
* the packet is being allocated with enough header space to be
* forwarded (to Ethernet for example).
*/
next_pbuf = pbuf_alloc(PBUF_LINK, 0, PBUF_POOL);
#else /* IP_FORWARD || LWIP_IPV6_FORWARD */
next_pbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (pcrx->in_head == NULL) {
pbuf_alloc_len = PBUF_LINK_HLEN;
}
#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */
next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL);
if (next_pbuf == NULL) {
/* No free buffers. Drop the input packet and let the
* higher layers deal with it. Continue processing
* the received pbuf chain in case a new packet starts. */
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE MBUFS!\n", pcb->num));
PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", pcb->num));
LINK_STATS_INC(link.memerr);
ppp_drop(pcrx);
pcrx->in_state = PDSTART; /* Wait for flag sequence. */
break;
}
if (pcrx->in_head == NULL) {
u8_t *payload;
/* pbuf_header() used below is only trying to put PPP headers
* before the current payload pointer if there is enough space
* in the pbuf to do so. Therefore we don't care if it fails,
* but if it fail we have to set len to the size used by PPP headers.
*/
u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len;
#if PPP_INPROC_MULTITHREADED
if (pbuf_header(next_pbuf, +sizeof(struct pppos_input_header) +sizeof(pcrx->in_protocol))) {
next_pbuf->len += sizeof(struct pppos_input_header) + sizeof(pcrx->in_protocol);
}
payload = next_pbuf->payload;
((struct pppos_input_header*)payload)->pcb = pcb;
payload += sizeof(struct pppos_input_header);
#else /* PPP_INPROC_MULTITHREADED */
if (pbuf_header(next_pbuf, +sizeof(pcrx->in_protocol))) {
next_pbuf->len += sizeof(pcrx->in_protocol);
}
payload = next_pbuf->payload;
next_pbuf->len += sizeof(struct pppos_input_header);
#endif /* PPP_INPROC_MULTITHREADED */
next_pbuf->len += sizeof(pcrx->in_protocol);
*(payload++) = pcrx->in_protocol >> 8;
*(payload) = pcrx->in_protocol & 0xFF;
pcrx->in_head = next_pbuf;