mirror of
https://github.com/ipxe/ipxe
synced 2026-10-07 15:05:42 +03:00
[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:
+10
-1
@@ -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
@@ -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 )
|
||||
|
||||
Reference in New Issue
Block a user