Errore di verifica delle dimensioni dei buffer
Quando si gestiscono IOCTLs e FSCTLs che implementano I/O buffer memorizzati nel buffer, un driver deve sempre controllare le dimensioni dei buffer di input e di output per garantire che i buffer possano contenere tutti i dati richiesti. Se la richiesta specifica FILE_ANY_ACCESS, come la maggior parte dei driver IOCTLs e FSCTLs, qualsiasi chiamante che dispone di un handle per il dispositivo ha accesso a richieste IOCTL o FSCTL memorizzate nel buffer e potrebbe leggere o scrivere dati oltre la fine del buffer.
Dimensioni del buffer di input
Si supponga, ad esempio, che il codice seguente venga visualizzato in una routine chiamata da una routine Dispatch e che il driver non abbia convalidato le dimensioni del buffer passate nell'IRP:
switch (ControlCode)
...
...
case IOCTL_NEW_ADDRESS:{
tNEW_ADDRESS *pNewAddress =
pIrp->AssociatedIrp.SystemBuffer;
pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);
L'esempio non controlla le dimensioni del buffer prima dell'istruzione di assegnazione (evidenziata). Di conseguenza, il riferimento pNewAddress-Address> nella riga successiva può essere danneggiato se il buffer di input non è abbastanza grande per contenere una struttura tNEW_ADDRESS.
Il codice seguente controlla le dimensioni del buffer, evitando il potenziale problema:
case IOCTL_NEW_ADDRESS: {
tNEW_ADDRESS *pNewAddress =
pIrp->AssociatedIrp.SystemBuffer;
if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >=
sizeof(tNEW_ADDRESS)) {
pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);
Il codice per gestire altre operazioni di I/O con buffer, ad esempio richieste WMI che usano buffer di dimensioni variabili, può avere errori simili.
Dimensioni del buffer di output
I problemi del buffer di output sono simili ai problemi del buffer di input. Possono facilmente danneggiare il pool e i chiamanti in modalità utente potrebbero non essere consapevoli che si è verificato un errore.
Nell'esempio seguente il driver non riesce a controllare le dimensioni di SystemBuffer:
case IOCTL_GET_INFO: {
Info = Irp->AssociatedIrp.SystemBuffer;
Info->NumIF = NumIF;
...
...
Irp->IoStatus.Information =
NumIF*sizeof(GET_INFO_ITEM)+sizeof(ULONG);
Irp->IoStatus.Status = ntStatus;
}
Supponendo che il campo NumIF del buffer di sistema specifica il numero di elementi di input, questo esempio può impostare IoStatus.Information su un valore maggiore del buffer di output e quindi restituire troppe informazioni al codice in modalità utente. Se un'applicazione viene codificata in modo errato e le chiamate con un buffer di output troppo piccolo, il codice precedente potrebbe danneggiare il pool scrivendo oltre la fine del buffer di sistema.
Tenere presente che il gestore di I/O presuppone che il valore nel campo Informazioni sia valido. Se un chiamante passa in un indirizzo in modalità kernel valido per il buffer di output e una dimensione pari a zero byte, i problemi gravi possono verificarsi se il driver non controlla le dimensioni del buffer di output e quindi trova l'errore.