Kernel programming and driver development are notoriously hard, the primary reason being that the programmer must display absolute accuracy. If there’s a single error or unchecked value, then the entire stability of the underlying operating system, and the machine as a whole, is in jeopardy.

As such, a kernel programmer’s best friend is the documentation of the kernel for their target platform. But sometimes programmers do not read the entire documentation for a given function, and even ignore the examples provided.

An example of this, discovered by Rootshell’s Research and Development team, is an incomplete patch made in the SoftEther VPN Project’s Windows kernel driver. The patch was made in 2019, yet it still contains a race condition in the user of the ‘Irp->UserBuffer’, between the call to ProbeForWrite and the use of the memory later. The issue is not addressed in the documentation:

“Drivers must call ProbeForWrite inside a try/except block. If the routine raises an exception, the driver should complete the IRP with the appropriate error. Note that subsequent accesses by the driver to the user-mode buffer must also be encapsulated within a try/except block.” (Source)

The affected code, along with the changes, is shown in the screenshot below:

MicrosoftTeams image 4

The fix for this issue is actually very simple. The entire block of code proceeding the try/except block should be removed and placed inside the ‘try’ block, thus heeding the warning given in the documentation:

“a malicious application could have another thread deleting, substituting, or changing the protection of user address ranges at any time (even after or during a call to ProbeForRead or ProbeForWrite).” (Source)

The Rootshell team have developed a proof of concept exploit for the issues, which results in a denial-of-service of the machine. This is due to a page fault (in the code shown above) in accessing memory that was paged upon the call to ‘ProbeForWrite’, but subsequently unpaged just prior to the dereference of ‘pStats’.

The driver is no longer in common use. But it serves as an example of how neglecting to read a kernel driver’s documentation in full can lead to invalid patches and, potentially, security risks to users.