| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two threads begin processing the identical response message, received
twice. The first thread, A, runs. While it's running, the second one, B,
gets partway through, and during that slow calculation, or even while
blocking on MuAcquirePushLockExclusive(), A completes and then also a
handshake initiation that's already been queued up runs in thread C,
which itself takes that same MuAcquirePushLockExclusive(). The handshake
initiation creation succeeds, and sets the state back to
waiting-for-response, and calls MuReleasePushLockExclusive(), at which
point thread B resumes, because either its finished its calculations or
was finally allowed to acquire MuAcquirePushLockExclusive(). Thread B
then copies the state back to the peer, and begins a new session, using
that state, which is the same session as the one made in thread A.
Thread A Thread B Thread C
MuAcquirePushLockShared()
sA = Handshake->State
RtlCopyMemory(cA, Handshake->crypto)
MuReleasePushLockShared()
if (sA != 1)
goto fail
SlowCrypto(cA)
MuAcquirePushLockShared()
sB = Handshake->State
RtlCopyMemory(cB, Handshake->crypto)
MuReleasePushLockShared()
if (sB != 1)
goto fail
SlowCrypto(cB)
MuAcquirePushLockExclusive()
if (sA != Handshake->State)
goto fail
RtlCopyMemory(Handshake->crypto, cA)
Handshake->State = 2
MuReleasePushLockExclusive()
MuAcquirePushLockExclusive()
if (Handshake->State != 2)
goto fail
DeriveSession(Handshake->crypto)
MuReleasePushLockExclusive()
MuAcquirePushLockExclusive()
SlowCrypto(Handshake->crypto)
Handshake->State = 1
MuReleasePushLockExclusive()
MuAcquirePushLockExclusive()
if (sB != Handshake->State)
goto fail
RtlCopyMemory(Handshake->crypto, cB)
Handshake->State = 2
MuReleasePushLockExclusive()
MuAcquirePushLockExclusive()
if (Handshake->State != 2)
goto fail
DeriveSession(Handshake->crypto)
MuReleasePushLockExclusive()
This seems basically impossible to hit in a meaningful way in practice,
but ensure that it absolutely cannot happen by comparing the ephemeral
private key that's on the stack with the latest one that the peer's
handshake state has.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
Otherwise a vetoed query-remove leaves the adapter permanently
inaccessible via ioctl, even though NDIS keeps the miniport alive and
operational.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
| |
CommandLineToArgvW("") returns the calling executable's path with
Argc=1, so a silent worker crash would be parsed as a path through
wcstoul, yielding either bogus error codes or, on UNC paths, a
silent ERROR_SUCCESS. Also deal with a zero sized response buffer, and
the case when the response fills the buffer precisely.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
| |
AdapterCleanupOrphanedDevices(TRUE) is called from DllMain's
DLL_PROCESS_ATTACH and queues CleanupOrphanedDevices onto a thread-pool
thread, where it runs long SetupAPI/CM operations and blocks on the
namespace mutexes. Pin the module before this happens, so that it can't
be unloaded while working.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
When Windows does major updates, it walks the driver store and manually
installs drivers into the ROOT namespace. This is a problem since we use
the SWD namespace. Since these nodes are never accounted for, they live
on and prevent the driver from ever being unloaded or upgraded.
Fix this by walking through the ROOT namespace and removing these
phantom drivers.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
We always have a file reference to get the proper nsi device object, so
rather than failing, in most cases, we can properly service these
requests.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
And also gate the PriorDispatch on the presence of an extension, which
NDIS always has.
Reported-by: Brian Diff <bdiff7311@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
| |
The stack version of this is never used, because it's long-lived, and so
we always read it out of the peer struct.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
| |
I fixed the CodeQL rules.
Link: https://github.com/microsoft/Windows-Driver-Developer-Supplemental-Tools/pull/217
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
| |
WSK's WskSendTo copies addresses and control messages synchronously
before returning STATUS_PENDING. Confirmed by reverse engineering
afd.sys!WskProIRPSendTo and tcpip.sys!UdpSendMessages, which consume
address and cmsg data in the transport dispatch call and store only the
completion callback and IRP in the NBL context.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use C23 typeof to eliminate redundant type parameters from the RCU
macros.
Also, drop mention of hoping to use alignas in TODO.md. It only goes on
members of structs, not the struct type itself, which I find
syntactically annoying, and it doesn't really confer any additional real
benefits.
Moving to C23 means that we must use __VA_OPT__.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This restores 217922a ("driver: device: hack around broken IP notifier
by hijacking \Device\Nsi"), but does it right, hopefully.
Since we're attaching to \Device\Nsi as a filter, we increment the
refcount of the driver, which means Unload doesn't get called until we
detach filtering. So we attach and detach on first and last device
creation and destruction.
A limitation of the old commit is that it missed notifications from
netsh, because netsh sets the subinterface mtu, not the interface mtu.
I've now updated the code to catch both updates. For WireGuard, they are
effectively the same.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
| |
This makes the re-arm logic work better.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
| |
This avoids having to cleanup if the version is wrong.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
| |
This matches the behavior on Linux and other operating systems. Before,
you could append a bunch of cruft, which would then not get copied to
the header, while the MAC checker would still look at the end of the
NBL, hashing garbage.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Bad flow:
- new event, Done
- first op finishes sync, so STATUS_SUCCESS, which isn't pending, Done
isn't consumed.
- next op finishes async, so STATUS_PENDING, so we wait on it, but it's
already consumed from before, so it doesn't wait.
Fix this the easy way by always resetting the event always.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
| |
Otherwise we leak table.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
If port 0 is passed, for a random port, it gets assigned on v4
allocation, and then can fail on v6 allocation it's already in use. In
that case, set the port back to 0 so that it can try a new random port.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
| |
This is better than returning garbage, in case we extend this later.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
| |
That's what we do for the others, so why not this one?
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The issue faced by 4309390 ("driver: ioctl: restore usage of
FunctionalDeviceObject->Reserved") wasn't that Windows 10 RTM didn't
have NdisWdfGetAdapterContextFromAdapterHandle(), but rather that
DispatchPnp was being called very early with a different device object.
We can fix this by simply testing to see if we have the right type of
device.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
|
| |
Further experiments with NdisWdfGetAdapterContextFromAdapterHandle
indicate it's probably less reliable than using ->Reserved, because it
means dereferencing DeviceExension.
Also get rid of the awkward IoctlHalt.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
|
| |
The stub device only exists momentarily to create the software registry
key for SuggestedInstanceId. Setting SWDeviceCapabilitiesDriverRequired
with empty hardware IDs violates the SwDeviceCreate API contract and
causes PnP to needlessly search for a driver for this transient device.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
If SnapshotConfigurationAndState fails, Configuration is left NULL, but
RestoreConfigurationAndState was called unconditionally, passing the
NULL pointer to DeviceIoControl.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
| |
The return code before was wrong, because WaitForSingleObject returns
WAIT_OBJECT_0 on success, not TRUE.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
| |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
| |
|
|
|
|
|
|
| |
This eliminates the need for a cross signing certificate, which is no
longer needed in the kernel and was never useful in userspace. And it
does the timestamp server correctly.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|