Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Sterowniki często akceptują bufory wejściowe z ze stałymi nagłówkami i końcowymi danymi o zmiennej długości, jak w poniższym przykładzie:
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 );
}
Jeśli WaitBuffer->NameLength jest bardzo dużą wartością ULONG, to dodanie jej do przesunięcia może spowodować przepełnienie liczby całkowitej. Zamiast tego sterownik powinien odjąć przesunięcie (stały rozmiar nagłówka) z InputBufferLength (rozmiar buforu) i przetestować, czy wynik pozostawia wystarczającą ilość miejsca dla WaitBuffer-NameLength> (dane o zmiennej długości), jak w poniższym przykładzie:
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 );
}
Innymi słowy, jeśli rozmiar bufora minus stały rozmiar nagłówka pozostawia mniej bajtów niż jest wymagane dla danych o zmiennej długości, zgłaszamy błąd.
Powyższe odejmowanie nie może być podpełnione, ponieważ pierwsza instrukcja if gwarantuje, że wartość InputBufferLength jest większa lub równa rozmiarowi WAIT_FOR_BUFFER.
Poniżej przedstawiono bardziej skomplikowany problem z przepełnieniem:
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;
}
W tym przykładzie podczas mnożenia może wystąpić przepełnienie całkowite. Jeśli rozmiar struktury SET_VALUE_INFO jest wielokrotnością 2, wartość NumEntries , taka jak 0x80000000 powoduje przepełnienie, gdy bity są przesunięte w lewo podczas mnożenia. Jednak rozmiar buforu przejdzie test weryfikacyjny, ponieważ przepełnienie powoduje, że rozmiar dwSize wydaje się dość mały. Aby uniknąć tego problemu, odejmij długości, jak w poprzednim przykładzie, podziel przez sizeof(SET_VALUE_INFO) i porównaj wynik z NumEntries.