net_new() creates a struct net_connection and calls arp_request() to resolve unicast addresses. On success, arp_request() will populate a buffer within the net_connection with the destination MAC address.
If arp_request() aborts due to an error, it will leave the global pending_arp.ether pointing at the buffer, which is promptly freed leading to a dangling pointer and a use-after-free if we happen to get an ARP response just after the error occurred. Fix this memory safety issue by always clearing all of pending_arp once we are done with it, including error cases. Reported-by: Sohaib Mohamed <[email protected]> Signed-off-by: Ahmad Fatoum <[email protected]> Link: https://lore.barebox.org/[email protected] Signed-off-by: Sascha Hauer <[email protected]> (cherry picked from commit effaa57f9a9476ecc5d07be92255769631ecb624) Signed-off-by: Ahmad Fatoum <[email protected]> --- net/net.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/net/net.c b/net/net.c index 795afed159aa..9c5999604b67 100644 --- a/net/net.c +++ b/net/net.c @@ -220,24 +220,28 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et ret = eth_send(edev, arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); if (ret) - return ret; + goto out; arp_start = get_time_ns(); while (pending_arp.ip) { - if (ctrlc()) - return -EINTR; + if (ctrlc()) { + ret = -EINTR; + goto out; + } if (is_timeout(arp_start, 3 * SECOND)) { printf("T "); arp_start = get_time_ns(); ret = eth_send(edev, arp_packet, ETHER_HDR_SIZE + ARP_HDR_SIZE); if (ret) - return ret; + goto out; retries++; } - if (retries > PKT_NUM_RETRIES) - return -ETIMEDOUT; + if (retries > PKT_NUM_RETRIES) { + ret = -ETIMEDOUT; + goto out; + } net_poll(); } @@ -245,7 +249,11 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et pr_debug("Got ARP REPLY for %pI4: %02x:%02x:%02x:%02x:%02x:%02x\n", &dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); - return 0; + +out: + pending_arp.ip = 0; + pending_arp.ether = NULL; + return ret; } void net_poll(void) -- 2.47.3
