Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los controladores suelen aceptar búferes de entrada con encabezados fijos y datos de longitud variable final, como en el ejemplo siguiente:
typedef struct _WAIT_FOR_BUFFER {
LARGE_INTEGER Timeout;
ULONG NameLength;
BOOLEAN TimeoutSpecified;
WCHAR Name[1];
} WAIT_FOR_BUFFER, *PWAIT_FOR_BUFFER;
if (InputBufferLength < sizeof(WAIT_FOR_BUFFER)) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
WaitBuffer = Irp->AssociatedIrp.SystemBuffer;
if (FIELD_OFFSET(WAIT_FOR_BUFFER, Name[0]) +
WaitBuffer->NameLength > InputBufferLength) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
Si WaitBuffer-NameLength> es un valor ULONG muy grande, agregarlo al desplazamiento podría provocar un desbordamiento entero. En su lugar, un controlador debe restar el desplazamiento (tamaño fijo de encabezado) de InputBufferLength (tamaño de búfer) y probar si el resultado deja suficiente espacio para waitBuffer-NameLength> (datos de longitud variable), como en el ejemplo siguiente:
if (InputBufferLength < sizeof(WAIT_FOR_BUFFER)) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
Return( STATUS_INVALID_PARAMETER );
}
WaitBuffer = Irp->AssociatedIrp.SystemBuffer;
if ((InputBufferLength -
FIELD_OFFSET(WAIT_FOR_BUFFER, Name[0]) <
WaitBuffer->NameLength) {
IoCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
return( STATUS_INVALID_PARAMETER );
}
Es decir, si el tamaño del búfer menos el tamaño fijo del encabezado deja menos del número de bytes necesarios para los datos de longitud variable, se devuelve un error.
La resta anterior no puede provocar un desbordamiento negativo porque la primera instrucción if garantiza que InputBufferLength sea mayor o igual al tamaño de WAIT_FOR_BUFFER.
A continuación se muestra un problema de desbordamiento más complicado:
case IOCTL_SET_VALUE:
dwSize = sizeof(SET_VALUE);
if (inputBufferLength < dwSize) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
dwSize = FIELD_OFFSET(SET_VALUE, pInfo[0]) +
pSetValue->NumEntries * sizeof(SET_VALUE_INFO);
if (inputBufferLength < dwSize) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
En este ejemplo, se puede producir un desbordamiento entero durante la multiplicación. Si el tamaño de la estructura SET_VALUE_INFO es un múltiplo de 2, un valor NumEntries como 0x80000000 da como resultado un desbordamiento, cuando los bits se desplazan a la izquierda durante la multiplicación. Sin embargo, el tamaño del búfer pasará la prueba de validación, ya que el desbordamiento hace que dwSize parezca bastante pequeño. Para evitar este problema, reste las longitudes como en el ejemplo anterior, divida por sizeof(SET_VALUE_INFO) y compare el resultado con NumEntries.