reactos/ntoskrnl/io/iomgr
Hermès Bélusca-Maïto 4ce819ca5a
[NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892)
CORE-17470

+ KdpDebugLogInit: Add resources cleanup in failure code paths.

Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2
initialization steps are performed.
These are necessary for any functionality KDBG needs, that would depend
on the NT I/O Manager and the storage and filesystem stacks to be running.
This includes, creating the debug log file, and for KDBG, loading its
KDBinit initialization file.

As a result, file debug logging is fixed.

The old ReactOS-specific (NT-incompatible) callback we did in the middle
of IoInitSystem() is removed, in favor of a runtime mechanism that should
work on Windows as well.

The idea for this new mechanism is loosely inspired by the TDL4 rootkit,
see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html
but contrary to it, a specific hook is used instead, as well as the
technique of driver reinitialization:
https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261

Its rationale is as follows:

We want to be able to perform I/O-related initialization (starting a
logger thread for file log debugging, loading KDBinit file for KDBG,
etc.). A good place for this would be as early as possible, once the
I/O Manager has started the storage and the boot filesystem drivers.

Here is an overview of the initialization steps of the NT Kernel and
Executive:
----
KiSystemStartup(KeLoaderBlock)
    if (Cpu == 0) KdInitSystem(0, KeLoaderBlock);
    KiSwitchToBootStack() -> KiSystemStartupBootStack()
    -> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock)

(NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); )
KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock);

ExpInitializeExecutive(Cpu == 0):    ExpInitializationPhase = 0;
    HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback.
    ...
    PsInitSystem(LoaderBlock)
        PsCreateSystemThread(Phase1Initialization)

Phase1Initialization(Discard):       ExpInitializationPhase = 1;
    HalInitSystem(1, KeLoaderBlock);
    ...
    Early initialization of Ob, Ex, Ke.
    KdInitSystem(1, KeLoaderBlock);
    ...
    KdDebuggerInitialize1(LoaderBlock);
    ...
    IoInitSystem(LoaderBlock);
    ...
----
As we can see, KdDebuggerInitialize1() is the last KD initialization
routine the kernel calls, and is called *before* the I/O Manager starts.
Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also,
we want to do the I/O initialization as soon as possible. There does
not seem to be any exported way to be notified about the I/O manager
initialization steps... that is, unless we somehow become a driver and
insert ourselves in the flow!

Since we are not a regular driver, we need to invoke IoCreateDriver()
to create one. However, remember that we are currently running *before*
IoInitSystem(), the I/O subsystem is not initialized yet. Due to this,
calling IoCreateDriver(), much like any other IO functions, would lead
to a crash, because it calls
ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType
is non-initialized yet (it's NULL).

The chosen solution is to hook a "known" exported callback: namely, the
HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver").
It is set very early on by the HAL via the HalInitSystem(0, ...) call,
and is called early on by IoInitSystem() before any driver is loaded,
but after the I/O Manager has been minimally set up so that new drivers
can be created.
When the hook: KdpInitDriver() is called, we create our driver with
IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then
restore and call the original HalInitPnpDriver() callback.

Another possible unexplored alternative, could be to insert ourselves
in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the
KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while
we may be able to do this, because boot-drivers are resident in memory,
much like we are, we cannot insert ourselves in the system-driver list
however, since those drivers are expected to come from PE image files.)

Once the KdpDriverEntry() driver entrypoint is called, we register
KdpDriverReinit() for re-initialization with the I/O Manager, in order
to provide more initialization points. KdpDriverReinit() calls the KD
providers at BootPhase >= 2, and schedules further reinitializations
(at most 3 more) if any of the providers request so.
2023-03-11 01:22:19 +01:00
..
adapter.c
arcname.c [NTOS:IO] Check RtlAnsiStringToUnicodeString return value when initializing Arc names 2021-06-28 10:20:57 +02:00
bootlog.c [REACTOS] Cleanup INIT and some PAGE section allocations 2020-11-02 21:45:31 +03:00
controller.c [NTOSKRNL] Fix indentation. No code changes. 2018-12-16 10:30:23 +01:00
device.c [NTOS:IO] Fix indentation. No code changes! 2020-03-21 14:32:18 +01:00
deviface.c [NTOS:IO] IoRegisterDeviceInterface: create non-volatile keys for new device interfaces 2022-03-28 08:13:05 +02:00
driver.c [NTOS:IO] Handle missing device instance in IopInitializeBuiltinDriver. CORE-18793 2023-01-14 17:52:17 -05:00
error.c [NTOS:IO] Be more specific for chasing CORE-17587 2021-05-26 11:03:34 +02:00
file.c [NTOS:IO] Properly zero-initialize a file object created by IopParseDevice (#4931) 2022-12-08 01:15:42 +03:00
iocomp.c [NTOSKRNL] Force a probe against ReturnLength on query & Misc ICIF stuff 2022-06-12 11:05:05 +02:00
ioevent.c
iofunc.c [NTOS:IO] Fail, if io completion port and an apc routine are used at the same time 2021-11-24 13:34:26 +01:00
iomdl.c [NTOSKRNL] Fix indentation. No code changes. 2018-12-19 19:18:20 +01:00
iomgr.c [NTOS:KD][KDBG] Rework the BootPhase >= 2 initialization of the KD/KDBG kernel debugger. (#4892) 2023-03-11 01:22:19 +01:00
iorsrce.c [NTOS:IO] Do not crash when calling IopLegacyResourceAllocation with NULL ResourceRequirements 2021-11-01 18:16:25 +01:00
iotimer.c [NTOS:IO/KD/KDBG] Formatting fixes only. 2023-03-09 18:26:02 +01:00
iowork.c
irp.c [NTOS:IO] Fix IRP stack location check in IoForwardIrpSynchronously 2020-09-07 04:57:17 +03:00
irq.c
ramdisk.c [NTOS:IO] Check RtlAnsiStringToUnicodeString return value when initializing ramdisk 2021-06-28 10:20:57 +02:00
rawfs.c [NTOS:RAWFS] LE JOKE! - Commit 7716bddd (r24564) claimed to "actually create the \\Device names so that user-mode can even talk to it", yet didn't bother to do that! 2021-09-26 03:02:58 +02:00
remlock.c
symlink.c
util.c Fix build (forgot a comma ;) 2019-06-11 22:36:10 +02:00
volume.c [REACTOS] Cleanup INIT and some PAGE section allocations 2020-11-02 21:45:31 +03:00