Erreurs lors du référencement d’adresses User-Space
Tout pilote, qu’il s’agisse de prendre en charge des irps ou des opérations d’E/S rapides, doit valider n’importe quelle adresse dans l’espace utilisateur avant d’essayer de l’utiliser. Le gestionnaire d’E/S ne valide pas ces adresses, ni les pointeurs incorporés dans les mémoires tampons passées aux pilotes.
Échec de la validation des adresses passées dans METHOD_NEITHER IOCTL et FSCTL
Le gestionnaire d’E/S n’effectue aucune validation pour METHOD_NEITHER IOCTL et FSCTL. Pour s’assurer que les adresses d’espace utilisateur sont valides, le pilote doit utiliser les routines ProbeForRead et ProbeForWrite , en plaçant toutes les références de mémoire tampon dans des blocs try/except .
Dans l’exemple suivant, le pilote suppose que la valeur passée dans type3InputBuffer représente une adresse valide.
case IOCTL_GET_HANDLER:
{
PULONG EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
*EntryPoint = (ULONG)DriverEntryPoint;
...
}
Le code suivant évite ce problème :
case IOCTL_GET_HANDLER:
{
PULONG_PTR EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
try
{
if (Irp->RequestorMode != KernelMode)
{
ProbeForWrite(EntryPoint,
sizeof(ULONG_PTR),
TYPE_ALIGNMENT(ULONG_PTR));
}
*EntryPoint = (ULONG_PTR)DriverEntryPoint;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
...
}
...
}
Notez également que le code correct caste DriverEntryPoint en ULONG_PTR, au lieu d’un ULONG. Cette modification permet une utilisation dans un environnement Windows 64 bits.
Échec de la validation des pointeurs incorporés dans les demandes d’E/S mises en mémoire tampon
Souvent, les pilotes incorporent des pointeurs dans des requêtes mises en mémoire tampon, comme dans l’exemple suivant :
struct ret_buf
{
void *arg; // Pointer embedded in request
int rval;
};
pBuf = Irp->AssociatedIrp.SystemBuffer;
...
arg = pBuf->arg; // Fetch the embedded pointer
...
// If the arg pointer is not valid, the following
// statement can corrupt the system:
RtlMoveMemory(arg, &info, sizeof(info));
Dans cet exemple, le pilote doit valider le pointeur incorporé à l’aide des routines Probe Xxx placées dans un bloc try/except de la même façon que pour les METHOD_NEITHER IOCTL décrites précédemment. Bien que l’incorporation d’un pointeur permette à un pilote de retourner des informations supplémentaires, un pilote peut obtenir plus efficacement le même résultat à l’aide d’un décalage relatif ou d’une mémoire tampon de longueur variable.
Pour plus d’informations sur l’utilisation de blocs try/except pour gérer des adresses non valides, consultez Gestion des exceptions.