On a store_block() failure httpc_recv_cb() calls altcp_abort(), which
frees the pcb, and then returns ERR_BUF. lwIP's receive-callback contract
requires ERR_ABRT once tcp_abort() has been called. On any other return
value tcp_input() keeps using the freed pcb (for example it stores the
segment in pcb->refused_data), a use-after-free.
Return ERR_ABRT so tcp_input() stops touching the pcb.
Fixes: 3c656c928bd7 ("net: lwip: add wget command")
Signed-off-by: Shahriyar Jalayeri <[email protected]>
---
net/lwip/wget.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/lwip/wget.c b/net/lwip/wget.c
index 247ece18e2b..9e93765926d 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -205,8 +205,12 @@ static err_t httpc_recv_cb(void *arg, struct altcp_pcb
*pcb, struct pbuf *pbuf,
for (buf = pbuf; buf; buf = buf->next) {
if (store_block(ctx, buf->payload, buf->len) < 0) {
+ /*
+ * altcp_abort() freed the pcb; the recv callback must
+ * return ERR_ABRT so tcp_input() stops using it.
+ */
altcp_abort(pcb);
- ret = ERR_BUF;
+ ret = ERR_ABRT;
goto out;
}
}
--
2.43.0