[fcoe] Add assorted length checks

Add an assortment of missing length checks that can currently result
in reads of uninitialised data from within the Ethernet frame padding
region of a received I/O buffer.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-08-04 13:51:08 +01:00
parent 894a7e04be
commit 5e706ff4c5
2 changed files with 24 additions and 4 deletions
+10 -1
View File
@@ -406,6 +406,8 @@ union fip_descriptor {
struct fip_descriptors {
/** Descriptors, indexed by type */
union fip_descriptor *desc[FIP_NUM_DESCRIPTOR_TYPES];
/** Descriptor lengths, indexed by type */
size_t len[FIP_NUM_DESCRIPTOR_TYPES];
};
/**
@@ -416,10 +418,17 @@ struct fip_descriptors {
* @v finder Descriptor finder
*/
#define FIP_DESCRIPTOR( type, name ) \
static inline __attribute__ (( always_inline )) size_t \
fip_ ## name ## _len ( struct fip_descriptors *descs ) { \
return (descs)->len[type]; \
} \
static inline __attribute__ (( always_inline )) \
typeof ( ( ( union fip_descriptor * ) NULL )->name ) * \
fip_ ## name ( struct fip_descriptors *descs ) { \
return &(descs->desc[type]->name); \
typeof ( ( ( union fip_descriptor * ) NULL )->name ) \
*ptr = &((descs)->desc[type]->name); \
size_t len = fip_ ## name ## _len (descs); \
return ( ( len >= sizeof ( *ptr ) ) ? ptr : NULL ); \
}
FIP_DESCRIPTOR ( FIP_PRIORITY, priority );
FIP_DESCRIPTOR ( FIP_MAC_ADDRESS, mac_address );
+14 -3
View File
@@ -496,7 +496,7 @@ static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
/* Parse descriptor list */
memset ( descs, 0, sizeof ( *descs ) );
for ( desc_offset = 0 ;
desc_offset <= ( descs_len - sizeof ( desc->common ) ) ;
( desc_offset + sizeof ( desc->common ) ) <= descs_len ;
desc_offset += desc_len ) {
/* Find descriptor and validate length */
@@ -518,8 +518,10 @@ static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
if ( ( desc_type > FIP_RESERVED ) &&
( desc_type < FIP_NUM_DESCRIPTOR_TYPES ) ) {
/* Use only the first instance of a descriptor */
if ( descs->desc[desc_type] == NULL )
if ( descs->desc[desc_type] == NULL ) {
descs->desc[desc_type] = desc;
descs->len[desc_type] = desc_len;
}
continue;
}
@@ -916,7 +918,7 @@ static int fcoe_fip_rx ( struct io_buffer *iobuf,
const void *ll_dest,
const void *ll_source __unused,
unsigned int flags __unused ) {
struct fip_header *fiphdr = iobuf->data;
struct fip_header *fiphdr;
struct fip_descriptors descs;
struct fip_handler *handler;
struct fcoe_port *fcoe;
@@ -944,6 +946,15 @@ static int fcoe_fip_rx ( struct io_buffer *iobuf,
goto done;
}
/* Sanity check */
if ( iob_len ( iobuf ) < sizeof ( *fiphdr ) ) {
DBGC ( fcoe, "FCoE %s received under-length FIP packet (%zd "
"bytes)\n", fcoe->netdev->name, iob_len ( iobuf ) );
rc = -EINVAL_UNDERLENGTH;
goto done;
}
fiphdr = iobuf->data;
/* Parse FIP packet */
if ( ( rc = fcoe_fip_parse ( fcoe, fiphdr, iob_len ( iobuf ),
&descs ) ) != 0 )