|
@@ -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
|
}
|