Commit graph

16 commits

Author SHA1 Message Date
George Bișoc f4de5ceb9e
[NTOS:CM] Implement cache lookup and cleanup subkey information for cache consistency
During an open or create procedure of a registry key, the registry parser grabs
a key control block (KCB) from the parser object and uses its information to do the
necessary work in order to obtain a pointer to the newly created or opened registry key.

However, the registry parsers faces several issues. First, we don't do subkey cache cleaning
information against gathered KCBs so whenever we do a registry parse we end up with KCBs
that have cache inconsistencies. Moreover we don't do any locking of whatever KCB we
are grabing during a parse procedure.

=== PROPOSED CHANGES ===

* Implement CmpComputeHashValue and CmpLookInCache functions. With CmpComputeHashValue we can
compute the convkey hashes of each subkey in the path name of a key so we can lock them
with CmpBuildAndLockKcbArray. CmpLookInCache is a function that searches for the suitable
KCB in the cache. The factors that determine if a KCB is "suitable" are:

-- the currently found KCB in the hash list has the same levels as that of the
given KCB from the parse object;

-- The key names from the computed hash values match with the block name of
the KCB;

-- The currently found KCB is not deleted.

The KCB will be changed if the key path name points to a partial match name in
the cache. The KCB from the parse object will be used if we have a full match
of remaining levels.

* Add missing CMP_LOCK_HASHES_FOR_KCB flags on CmpCreateKeyControlBlock calls
that create KCBs during a parse procedure. Such lock has to be preserved until
we're done with the registry parsing.

* On CmpDoCreateChild, preserve the exclusive lock of the KCB when we are
enlisting the key body.

* On CmpDoCreate, make sure that the passed parent KCB is locked exclusively and
lock the hiver flusher as we don't want the flusher to kick in during a key
creation on the given hive. Cleanup the subkey info when we're creating a key
object. Also implement missing cleanup path codes. Furthermore, avoid key
object creation if the parent KCB is protected with a read-only switch.

* Soft rewrite the CmpDoOpen function, namely how we manage a direct open vs
create KCB on open scenario. When a KCB is found in cache avoid touching
the key node. If the symbolic link has been resolved (aka found) then lock
exclusively the symbolic KCB. Otherwise just give the cached KCB to the caller.

If it were for the caller to request a KCB creation, we must check the passed
KCB from the parser object is locked exclusively, unlike on the case above
the caller doesn't want to create a KCB because there's already one in the cache.
We don't want anybody to touch our KCB while we are still toying with it during
its birth. Furthermore, enlist the key body but mind the kind of lock it's been
used.

* On CmpCreateLinkNode, avoid creating a key object if the parent KCB is protected
with a read-only switch. In addition, add missing hive flusher locks for both
the target hive and its child. Cleanup the subkey information of the KCB when
creating a link node, this ensures our cached KCB data remains consistent.

* Do a direct open on CmpParseKey if no remaining subkey levels have been found
during hash computation and cache lookup, in this case the given KCB is the
block that points to the exact key. This happens when for example someone tried
to call RegOpenKeyExW but submitting NULL to the lpSubKey argument parameter.

CORE-10581
ROSTESTS-198
2023-10-01 20:06:02 +02:00
George Bișoc 8cb56e77a6
[NTOS:CM] Do not call CmpSecurityMethod when assigning a security descriptor
CmpSecurityMethod is a method used by the Object Manager and called by this
subsystem whenever a security operation has to be done against a key object.

As CmpSecurityMethod is a specific OB construct we should not make any direct
call attempts to CmpSecurityMethod, only OB is responsible for that. This fixes
a deadlock where CmpSecurityMethod acquires a push lock for exclusive access
even though such lock is already acquired by the same calling thread in
CmpDoCreateChild.
2023-10-01 20:06:02 +02:00
George Bișoc 697a52aa33
[NTOS:CM] Do not acquire the lock twice when the Object Manager calls CmpSecurityMethod
Whenever a security request is invoked into a key object, such as when requesting
information from its security descriptor, the Object Manager will execute
the CmpSecurityMethod method to do the job.

The problem is that CmpSecurityMethod is not aware if the key control block
of the key body already has a lock acquired which means the function will attempt
to acquire a lock again, leading to a deadlock. This happens if the same
calling thread locks the KCB but it also wants to acquire security information
with ObCheckObjectAccess in CmpDoOpen.

Windows has a hack in CmpSecurityMethod where the passed KCB pointer is ORed
with a bitfield mask to avoid locking in all cases. This is ugly because it negates
every thread to acquire a lock if at least one has it.
2023-10-01 20:06:02 +02:00
George Bișoc 08fcf0c58b
[NTOS:CM] Implement locking/unlocking of KCBs in an array
The CmpUnLockKcbArray, CmpLockKcbArray and CmpBuildAndLockKcbArray routines
help us to lock KCBs within array so that information remains consistent when
we are doing a cache lookup during a parse procedure of the registry database.
2023-10-01 20:06:01 +02:00
George Bișoc c6230ba255
[NTOS:CM] Add KCB array lock function prototypes & Other Stuff
Implement CmpBuildAndLockKcbArray and CmpUnLockKcbArray prototypes, we'll gonna need these
to do the locking/unlocking of KCBs stacked up in an array. In addition implement some CM
constructs specifically for cache lookup implementation (more at documentation remarks).

=== DOCUMENTATION REMARKS ===

CMP_SUBKEY_LEVELS_DEPTH_LIMIT -- This is the limit of up to 32 subkey levels
that the registry can permit. This is used in CmpComputeHashValue to ensure
that we don't compute more than the limit of subkeys we're allowed to.

CMP_KCBS_IN_ARRAY_LIMIT -- This is equal to CMP_SUBKEY_LEVELS_DEPTH_LIMIT
plus the addition by 2. This construct is used as a limit of KCB elements
the array can hold. 2 serves as an additional space for the array (one for
the root object and another one as extra space so we don't blow up the stack
array).

CMP_LOCK_KCB_ARRAY_EXCLUSIVE & CMP_LOCK_KCB_ARRAY_SHARED -- These flags are used exclusively
for CmpBuildAndLockKcbArray and CmpLockKcbArray. Their meaning are obvious.

CM_HASH_CACHE_STACK -- A structure used to store the hashes of KCBs for locking. It is named
"stack" because the way we store the hashes of KCBs is within an auxilliary "outer stack array".
2023-10-01 20:06:01 +02:00
George Bișoc 54a00aa8eb
[CMLIB][NTOS:CM] Deduplicate other common definitions between CMLIB and the NTOS CM
Addendum to commit 8c2454e (r70605). Credits and courtesy go to Hermès BÉLUSCA - MAÏTO.

CORE-10802 CORE-10793
2022-07-10 14:35:53 +02:00
Hermès Bélusca-Maïto 6ff0232368
[NTOS:CM] Adapt cmboot.c for usage in NT/ReactOS bootloader.
- Add a new cmboot.h header to isolate the boot-support definitions
  shared with the NT/ReactOS bootloader.

- Move CmpFreeDriverList() to cmboot.c so that we can use it for
  cleanup paths in the NT/ReactOS bootloader.

- CmpFindControlSet(): Directly build the control set name in UNICODE,
  instead of doing an ANSI->UNICODE conversion.

- Directly assign the CurrentControlSet\Services constant string,
  instead of going the route of init-empty-string + append-string.
  This is possible since that string is not modified later.

- Remove ASSERT(FALSE), replacing them with correct failure handling.

- Add cleanup paths in CmpAddDriverToList().

- Simplify and fix CmpFreeDriverList(): it's the full DriverNode
  that needs to be freed; not the LIST_ENTRY pointer.

- Add other validity checks:
  * Registry value types and data sizes;
  * For multi-strings, verify that they are NULL-terminated.
  * For (multi-)strings, check whether they are NULL-terminated before
    optionally removing their trailing NULL character from the count.
    Check also whether they are of zero-length and take appropriate
    action where necessary.

- Add CmpIsDriverInList() for future usage in CMBOOT compiled in
  bootloader mode.

- Add SAL annotations and Doxygen documentation.

- Add debug traces.

- Formatting / code style fixes.

** TODO: Fix SafeBoot support **
2022-04-16 18:37:45 +02:00
Jérôme Gardou 3adf450867 [REACTOS] Addendum to 5c7ce4475e - Fix MSVC 2015 build
Put data into PAGEDATA or INITDATA sections
Keep section declaration for prototypes

CORE-17540
2021-05-12 11:04:29 +02:00
Victor Perevertkin 5c7ce4475e
[REACTOS] Cleanup INIT and some PAGE section allocations
- Change INIT_FUNCTION and INIT_SECTION to CODE_SEG("INIT") and DATA_SEG("INIT") respectively
- Remove INIT_FUNCTION from function prototypes
- Remove alloc_text pragma calls as they are not needed anymore
2020-11-02 21:45:31 +03:00
Timo Kreuzer b82bf8ce16
[NTOS:IO] Fix parsing of resource lists
Also add a hack to avoid failing on now occurring resource conflict detection and try to fix at least one resource in ACPI hal.

CORE-10146
CORE-12892
2020-04-24 13:58:09 +03:00
Timo Kreuzer 71fefa32db
[NDK][NTOS] Add global definition of INIT_FUNCTION/INIT_SECTION (#779)
* Add an NDK header to define INIT_FUNCTION/INIT_SECTION globally
* Use _declspec(allocate(x)) and _declspec(code_seg(x)) on MSVC versions that support it
* Use INIT_FUNCTION on functions only and INIT_SECTION on data only (required by MSVC)
* Place INIT_FUNCTION before the return type (required by MSVC)
* Make sure declarations and implementations share the same modifiers (required by MSVC)
* Add a global linker option to suppress warnings about defined but unused INIT section
* Merge INIT section into .text in freeldr
2018-12-30 12:19:11 +01:00
Eric Kohl 167bffd80f [NTOSKRNL] Add and call the CmpSaveBootControlSet() stub. 2018-12-16 12:49:59 +01:00
Hermès Bélusca-Maïto 2ed65d1555
[NTOS] Configuration Manager fixes.
- Rework CmpSetSystemValues() and remove its 1st-stage text-mode setup hack, since a real registry hive will be used for 1st-stage either.
- Lock, then unlock the registry in NtInitializeRegistry when initializing the hives & flusher.
- Call CmpInitializeHiveList() (i.e., initialize the other hives like \Software, \User, \.Default) only when we are not in setup-mode.

svn path=/branches/setup_improvements/; revision=74747
2018-10-25 00:40:02 +02:00
Hermès Bélusca-Maïto d61c00c252
[NTOS:CM] Implement more support for force-unloading registry hives.
CORE-13448 CORE-10705
2018-10-22 00:05:13 +02:00
Serge Gautherie 7d6bda16c6
[REACTOS] Improve how some ASSERTMSG() message values are printed: enforce ending "\n".
NB: Not touching calls in "third-party" code: class and classpnp.
2018-08-08 22:03:45 +02:00
Colin Finck c2c66aff7d Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys. 2017-10-03 07:45:34 +00:00
Renamed from reactos/ntoskrnl/include/internal/cm.h (Browse further)