Pull request for UEFI sub-system for efi-2021-01-rc1 (2)
A use after free in the UEFI network stack is fixed. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl+N/tQACgkQxIHbvCwF GsTxbBAAmiql4LcM9DeSZPjRpza92PeYcsu0ZErvRgFJ2HdY88RpvK3UBeJRul2y CqdajQmusPX3mcCdwKVdLPiesAhDq5bOuZ5OPwixpkYr8QgFavkvN2YQLYm1Qzc7 wc21QKET82lp4Xzc9qnIPtOheP6GPwN3Bvpgy2OaRviqiD82Ezp59D/9hjw5vu0p /SzFibYzZqyGGJiNk3sRSmxPa+mTZ1Zd3hq+ZFDEyw3SNcWtJ5bhFv/sl0CWVOOJ HGRVh6KfgW63ZNwyy4NYojUE5H62+l+AMYeNYf1zdFWtS2y1dxP3sP7IP/UizA3C UAYuq8qIuz8F1Hue29bbZcPVvge5bBou0B7ocO2B7mOqkr3ttKVBjXuJkkuTc4nm DcpqVZsbTV8gdmFNeX7BEAWjCGnzWxjlG8AOdb3VQHX/Trx1n1NxIerqF5pNny6w Vakh71DAxT782YoCHzJG3NJfRwLek7XfedNZhpbWgLd+uSIgDotMxyoMVYLxN3Vz 98ejZ0XP9XDFgrpNjQqmBC3Re+CSmU3n8amIyG8SHkd4QiroCC0O7qRhamjq1JAu w2XsPfaJyOJ9ugzy+LB5/SbRPMlZu6Cr3wahNyBmpOmGyDOpRwKXJB7gjljMndnQ IXVw3ADpqHyymsOikD/NDCSvJQWWWIGtPMpzT0CjWGfa6iwZmBU= =YCCZ -----END PGP SIGNATURE----- Merge tag 'efi-2021-01-rc1-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi Pull request for UEFI sub-system for efi-2021-01-rc1 (2) A use after free in the UEFI network stack is fixed.
This commit is contained in:
commit
5d92dacbbe
3 changed files with 73 additions and 24 deletions
|
@ -44,6 +44,9 @@ struct udevice;
|
|||
|
||||
#define PKTALIGN ARCH_DMA_MINALIGN
|
||||
|
||||
/* Number of packets processed together */
|
||||
#define ETH_PACKETS_BATCH_RECV 32
|
||||
|
||||
/* ARP hardware address length */
|
||||
#define ARP_HLEN 6
|
||||
/*
|
||||
|
|
|
@ -24,9 +24,12 @@ static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
|
|||
static const efi_guid_t efi_pxe_base_code_protocol_guid =
|
||||
EFI_PXE_BASE_CODE_PROTOCOL_GUID;
|
||||
static struct efi_pxe_packet *dhcp_ack;
|
||||
static bool new_rx_packet;
|
||||
static void *new_tx_packet;
|
||||
static void *transmit_buffer;
|
||||
static uchar **receive_buffer;
|
||||
static size_t *receive_lengths;
|
||||
static int rx_packet_idx;
|
||||
static int rx_packet_num;
|
||||
|
||||
/*
|
||||
* The notification function of this event is called in every timer cycle
|
||||
|
@ -115,6 +118,8 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
|
|||
} else {
|
||||
/* Disable hardware and put it into the reset state */
|
||||
eth_halt();
|
||||
/* Clear cache of packets */
|
||||
rx_packet_num = 0;
|
||||
this->mode->state = EFI_NETWORK_STOPPED;
|
||||
}
|
||||
out:
|
||||
|
@ -160,6 +165,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
|
|||
net_init();
|
||||
/* Disable hardware and put it into the reset state */
|
||||
eth_halt();
|
||||
/* Clear cache of packets */
|
||||
rx_packet_num = 0;
|
||||
/* Set current device according to environment variables */
|
||||
eth_set_current();
|
||||
/* Get hardware ready for send and receive operations */
|
||||
|
@ -602,16 +609,16 @@ static efi_status_t EFIAPI efi_net_receive
|
|||
break;
|
||||
}
|
||||
|
||||
if (!new_rx_packet) {
|
||||
if (!rx_packet_num) {
|
||||
ret = EFI_NOT_READY;
|
||||
goto out;
|
||||
}
|
||||
/* Fill export parameters */
|
||||
eth_hdr = (struct ethernet_hdr *)net_rx_packet;
|
||||
eth_hdr = (struct ethernet_hdr *)receive_buffer[rx_packet_idx];
|
||||
protlen = ntohs(eth_hdr->et_protlen);
|
||||
if (protlen == 0x8100) {
|
||||
hdr_size += 4;
|
||||
protlen = ntohs(*(u16 *)&net_rx_packet[hdr_size - 2]);
|
||||
protlen = ntohs(*(u16 *)&receive_buffer[rx_packet_idx][hdr_size - 2]);
|
||||
}
|
||||
if (header_size)
|
||||
*header_size = hdr_size;
|
||||
|
@ -621,17 +628,22 @@ static efi_status_t EFIAPI efi_net_receive
|
|||
memcpy(src_addr, eth_hdr->et_src, ARP_HLEN);
|
||||
if (protocol)
|
||||
*protocol = protlen;
|
||||
if (*buffer_size < net_rx_packet_len) {
|
||||
if (*buffer_size < receive_lengths[rx_packet_idx]) {
|
||||
/* Packet doesn't fit, try again with bigger buffer */
|
||||
*buffer_size = net_rx_packet_len;
|
||||
*buffer_size = receive_lengths[rx_packet_idx];
|
||||
ret = EFI_BUFFER_TOO_SMALL;
|
||||
goto out;
|
||||
}
|
||||
/* Copy packet */
|
||||
memcpy(buffer, net_rx_packet, net_rx_packet_len);
|
||||
*buffer_size = net_rx_packet_len;
|
||||
new_rx_packet = 0;
|
||||
this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
|
||||
memcpy(buffer, receive_buffer[rx_packet_idx],
|
||||
receive_lengths[rx_packet_idx]);
|
||||
*buffer_size = receive_lengths[rx_packet_idx];
|
||||
rx_packet_idx = (rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV;
|
||||
rx_packet_num--;
|
||||
if (rx_packet_num)
|
||||
wait_for_packet->is_signaled = true;
|
||||
else
|
||||
this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
|
||||
out:
|
||||
return EFI_EXIT(ret);
|
||||
}
|
||||
|
@ -664,7 +676,26 @@ void efi_net_set_dhcp_ack(void *pkt, int len)
|
|||
*/
|
||||
static void efi_net_push(void *pkt, int len)
|
||||
{
|
||||
new_rx_packet = true;
|
||||
int rx_packet_next;
|
||||
|
||||
/* Check that we at least received an Ethernet header */
|
||||
if (len < sizeof(struct ethernet_hdr))
|
||||
return;
|
||||
|
||||
/* Check that the buffer won't overflow */
|
||||
if (len > PKTSIZE_ALIGN)
|
||||
return;
|
||||
|
||||
/* Can't store more than pre-alloced buffer */
|
||||
if (rx_packet_num >= ETH_PACKETS_BATCH_RECV)
|
||||
return;
|
||||
|
||||
rx_packet_next = (rx_packet_idx + rx_packet_num) %
|
||||
ETH_PACKETS_BATCH_RECV;
|
||||
memcpy(receive_buffer[rx_packet_next], pkt, len);
|
||||
receive_lengths[rx_packet_next] = len;
|
||||
|
||||
rx_packet_num++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -689,20 +720,14 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event,
|
|||
if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
|
||||
goto out;
|
||||
|
||||
if (!new_rx_packet) {
|
||||
if (!rx_packet_num) {
|
||||
push_packet = efi_net_push;
|
||||
eth_rx();
|
||||
push_packet = NULL;
|
||||
if (new_rx_packet) {
|
||||
/* Check that we at least received an Ethernet header */
|
||||
if (net_rx_packet_len >=
|
||||
sizeof(struct ethernet_hdr)) {
|
||||
this->int_status |=
|
||||
EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
|
||||
wait_for_packet->is_signaled = true;
|
||||
} else {
|
||||
new_rx_packet = 0;
|
||||
}
|
||||
if (rx_packet_num) {
|
||||
this->int_status |=
|
||||
EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
|
||||
wait_for_packet->is_signaled = true;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
@ -830,6 +855,7 @@ efi_status_t efi_net_register(void)
|
|||
{
|
||||
struct efi_net_obj *netobj = NULL;
|
||||
efi_status_t r;
|
||||
int i;
|
||||
|
||||
if (!eth_get_dev()) {
|
||||
/* No network device active, don't expose any */
|
||||
|
@ -847,6 +873,21 @@ efi_status_t efi_net_register(void)
|
|||
goto out_of_resources;
|
||||
transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
|
||||
|
||||
/* Allocate a number of receive buffers */
|
||||
receive_buffer = calloc(ETH_PACKETS_BATCH_RECV,
|
||||
sizeof(*receive_buffer));
|
||||
if (!receive_buffer)
|
||||
goto out_of_resources;
|
||||
for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
|
||||
receive_buffer[i] = malloc(PKTSIZE_ALIGN);
|
||||
if (!receive_buffer[i])
|
||||
goto out_of_resources;
|
||||
}
|
||||
receive_lengths = calloc(ETH_PACKETS_BATCH_RECV,
|
||||
sizeof(*receive_lengths));
|
||||
if (!receive_lengths)
|
||||
goto out_of_resources;
|
||||
|
||||
/* Hook net up to the device list */
|
||||
efi_add_handle(&netobj->header);
|
||||
|
||||
|
@ -941,7 +982,12 @@ failure_to_add_protocol:
|
|||
return r;
|
||||
out_of_resources:
|
||||
free(netobj);
|
||||
/* free(transmit_buffer) not needed yet */
|
||||
free(transmit_buffer);
|
||||
if (receive_buffer)
|
||||
for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++)
|
||||
free(receive_buffer[i]);
|
||||
free(receive_buffer);
|
||||
free(receive_lengths);
|
||||
printf("ERROR: Out of memory\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
|
|
@ -383,7 +383,7 @@ int eth_rx(void)
|
|||
|
||||
/* Process up to 32 packets at one time */
|
||||
flags = ETH_RECV_CHECK_DEVICE;
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
|
||||
ret = eth_get_ops(current)->recv(current, flags, &packet);
|
||||
flags = 0;
|
||||
if (ret > 0)
|
||||
|
|
Loading…
Reference in a new issue