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

Loading…
Cancel
Save