Browse Source

[efi] Check buffer length for packets retrieved via our SNP protocol

We do not currently check the length of the caller's buffer for
received packets.  This creates a potential buffer overrun when iPXE
is being used via the SNP or UNDI protocols.

Fix by checking the buffer length and correctly returning the required
length and an EFI_BUFFER_TOO_SMALL error.

Reported-by: Paul McMillan <paul.mcmillan@oracle.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
3f429bdcfe
1 changed files with 14 additions and 3 deletions
  1. 14
    3
      src/interface/efi/efi_snp.c

+ 14
- 3
src/interface/efi/efi_snp.c View File

@@ -710,6 +710,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
710 710
 	const void *iob_ll_src;
711 711
 	uint16_t iob_net_proto;
712 712
 	unsigned int iob_flags;
713
+	size_t max_len;
713 714
 	int rc;
714 715
 
715 716
 	DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
@@ -722,19 +723,28 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
722 723
 	/* Poll the network device */
723 724
 	efi_snp_poll ( snpdev );
724 725
 
725
-	/* Dequeue a packet, if one is available */
726
+	/* Check for an available packet */
726 727
 	iobuf = list_first_entry ( &snpdev->rx, struct io_buffer, list );
727 728
 	if ( ! iobuf ) {
728 729
 		DBGC2 ( snpdev, "\n" );
729 730
 		rc = -EAGAIN;
730 731
 		goto out_no_packet;
731 732
 	}
732
-	list_del ( &iobuf->list );
733 733
 	DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
734 734
 
735
+	/* Check buffer length */
736
+	max_len = *len;
737
+	*len = iob_len ( iobuf );
738
+	if ( *len > max_len ) {
739
+		rc = -ERANGE;
740
+		goto out_too_long;
741
+	}
742
+
743
+	/* Dequeue packet */
744
+	list_del ( &iobuf->list );
745
+
735 746
 	/* Return packet to caller */
736 747
 	memcpy ( data, iobuf->data, iob_len ( iobuf ) );
737
-	*len = iob_len ( iobuf );
738 748
 
739 749
 	/* Attempt to decode link-layer header */
740 750
 	if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
@@ -759,6 +769,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
759 769
 
760 770
  out_bad_ll_header:
761 771
 	free_iob ( iobuf );
772
+ out_too_long:
762 773
  out_no_packet:
763 774
 	return EFIRC ( rc );
764 775
 }

Loading…
Cancel
Save