Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os drivers geralmente aceitam buffers de entrada com cabeçalhos fixos seguidos por dados de comprimento variável, como no exemplo a seguir:
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 );
}
Se o WaitBuffer-NameLength for um valor ULONG muito grande, somar esse valor ao deslocamento pode causar um estouro de inteiro. Em vez disso, um driver deve subtrair o deslocamento (tamanho de cabeçalho fixo) do InputBufferLength (tamanho do buffer) e testar se o resultado deixa espaço suficiente para o WaitBuffer-NameLength> (dados de comprimento variável), como no exemplo a seguir:
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 );
}
Em outras palavras, se o tamanho do buffer menos o tamanho do cabeçalho fixo deixar menos do que o número de bytes necessários para os dados de comprimento variável, indicamos falha.
A subtração acima não pode causar subfluxo porque a instrução if inicial assegura que o InputBufferLength seja maior ou igual ao tamanho de WAIT_FOR_BUFFER.
O seguinte mostra um problema de overflow mais 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;
}
Neste exemplo, um estouro de número inteiro pode ocorrer durante a multiplicação. Se o tamanho da estrutura SET_VALUE_INFO for um múltiplo de 2, um valor NumEntries como 0x80000000 resulta em um estouro, quando os bits são deslocados para a esquerda durante a multiplicação. No entanto, o tamanho do buffer passará no teste de validação, porque o estouro faz com que dwSize pareça muito pequeno. Para evitar esse problema, subtraia os comprimentos como no exemplo anterior, divida por sizeof(SET_VALUE_INFO) e compare o resultado com NumEntries.