reactos/reactos/ntoskrnl/config
Sir Richard 143221853b [NTOS]: Fix for the the bug that broke ARM3 paged pool (and has been corrupting ReactOS paged pool behind the scenes for years):
When a KCB (key stuff) is allocated, the key name associated with it receives an NCB (name stuff). In case this name is already used, a cache exists, and an existing NCB is grabbed, and its reference count is increased. When the KCB goes away, its NCB loses a reference. When all references are gone, the NCB is destroyed. Simple enough.
        It turns out that what was currently happening is that an NCB would get dereferenced to 0, deleted, but still remained attached to a valid KCB (shouldn't happen). When that KCB went away, the NCB's reference count was dropped to... -1, and then -2, -3, -4, etc. Remember this is a FREED NCB. In other words, freed pool, that might now belong to someone else, was getting "-1" operations on it. So any value stored in that freed pool would get decremented by one. In ARM3 paged pool, because the allocator keeps a linked list, what would happen is that the FLINK pointer would be 0xE0F01234 instead of 0xE1A01234. What happened is that "0xE1A0" was treated as the reference count of the freed NCB, and it kept getting dereferenced down to 0xE0F0.
        Proving this was easy, by adding an ASSERT(Ncb->RefCount >= 1) to the routine that dereferences NCBs. Obviously, we should not try to dereference an NCB that has a reference count of 0, because that NCB is now gone. Adding this ASSERT immediately caught the error, regardless of which pool implementation was being used, so this was a problem in ReactOS today, right now.
        My first thought was that we were taking references to NCBs without incrementing the reference count. The NCB gets referenced in two places: when it gets created, and everytime a cached NCB is re-used for a new KCB (all this in CmpGetNameControlBlock).
	After adding some tracing code, I discovered that CmpGetNameControlBlock would sometimes return an NCB that was cached, but without referencing it. I did not understand why, since the code says "if (Found) Ncb->RefCount++".
        Further analysis showed that what would happen, on this particular instance, is that NCB "Foo" was being Found, but NCB "Bar" was returned instead. Therefore, causing some serious issues: First, NCB Foo was receiving too many references. Secondly, NCB Bar was not being referenced.
        Worse though, it turns out this would happen when "Foo" was the CORRECT NCB, and "Bar" was an INCORRECT NCB. What do we mean by correct and incorrect? Well, because NCBs are hashed, it's possible for two NCB hashes to be VERY SIMILAR, but only ONE OF THOSE NCBs will be the right one -- for example, HKLM\Software\Hello vs HKLM\Software\Hell.
        In our case, when a KCB for "Hello" was searching for the "Hello" NCB, the "Hello NCB would get a reference, but the "Hell" NCB would be returned. In other words, whenever a HASH COLLISION happened, the incorrect NCB was returned, probably messing up registry code in the process. Subsequently, when the KCB was dereferneced, it was attached to this incorrect, under-referenced NCB.
        Since in ANY hash collision with "Hell", in our example, the "Hell" NCB would come first, subsequent searches for "Hellmaster", "Hellboy", "Hello World" would all still return "Hell". Eventually when all these KCBs would go away, the "Hell" NCB would reach even -18 references.
        The simple solution? When the CORRECT NCB is found, STOP SEARCHING! By adding a simple "break" statement. Otherwise, even after the correct NCB is found, further, incorrect, collided NCBs are found, and eventually the last one ("Hell", in our example) got returned, and under-referenced, while "Hellmaster" and "Hellboy" were not returned, but LEAKED REFERENCES.
        There you have it folks, MEMORY CORRUPTION (USE-AFTER-FREE), INCORRECT REGISTRY NAME PARSHING, REFERENCE LEAKS and REFERENCE UNDERRUNS, all due to ONE missing "break;".
        -r

svn path=/trunk/; revision=47605
2010-06-06 01:04:03 +00:00
..
arm - Implement beginnings of Ramdisk Port Driver. Planning compatibility with ISO, SDI and WIM files and full Windows support. 2008-06-29 02:58:05 +00:00
i386 - Change CPUID to match the old Ki386Cpuid and take 4 output arguments instead of an array. This way we save some stack when using a dummy cpuid for synchronization and can query only the registers we want in the case we don't want all 4. 2009-09-27 10:09:38 +00:00
powerpc - Implement NtCreateKey using the new parse routine. 2007-12-15 18:14:41 +00:00
cmalloc.c [NTOSKRNL/CONFIG] 2010-03-26 08:39:27 +00:00
cmapi.c [NTOSKRNL/CONFIG] 2010-04-03 20:22:32 +00:00
cmboot.c [NTOS]: Implement Configuration Manager routines for building a driver list, sorting it, detecting circular dependencies and ordering, combining groups, tags, group orders and tag orders, etc. Replaces the "drvrlist" I/O interface currently in ReactOS. 2010-04-03 07:44:38 +00:00
cmcheck.c - Implement NtCreateKey using the new parse routine. 2007-12-15 18:14:41 +00:00
cmconfig.c Replace some ExFreePool by ExFreePoolWithTag 2008-08-31 15:29:21 +00:00
cmcontrl.c - Use CmPrepareKey only in cmlib, since it's a cmlib hack. 2007-12-15 18:25:08 +00:00
cmdata.c [NTOS]: Read almost all the Memory Management variables into the system configuration vector. These includes pool limits, percentages, debugging flags, behavioral changes, and others. 2010-04-20 22:47:51 +00:00
cmdelay.c [3DTEXT, FREELDR, HAL, MINGW_COMMON, MMDRV, MSGINA, NTOSKRNL] Add extern. 2009-10-18 18:52:56 +00:00
cmhook.c - Get rid of TAG() from the kernel 2009-08-24 18:19:53 +00:00
cmhvlist.c [NTOSKRNL/CONFIG] 2010-04-03 20:22:32 +00:00
cmindex.c [ntoskrnl\config] 2009-12-09 14:15:11 +00:00
cminit.c [NTOSKRNL/CONFIG] 2010-04-03 20:22:32 +00:00
cmkcbncb.c [NTOS]: Fix for the the bug that broke ARM3 paged pool (and has been corrupting ReactOS paged pool behind the scenes for years): 2010-06-06 01:04:03 +00:00
cmkeydel.c - Implement NtCreateKey using the new parse routine. 2007-12-15 18:14:41 +00:00
cmlazy.c [NTOS]: Implement CmSetLazyFlushState to disable lazy writing in the Cm. 2010-03-08 20:37:24 +00:00
cmmapvw.c - A bit of cleanup (no code change). 2007-12-16 17:23:38 +00:00
cmname.c - Implement NtCreateKey using the new parse routine. 2007-12-15 18:14:41 +00:00
cmnotify.c [NTOSKRNL/CONFIG] 2010-03-31 14:10:24 +00:00
cmparse.c [NTOSKRNL/CONFIG] 2010-04-03 20:22:32 +00:00
cmquota.c [NTOSKRNL/CONFIG] 2010-03-31 14:10:24 +00:00
cmse.c Replace some ExFreePool by ExFreePoolWithTag 2008-08-31 15:29:21 +00:00
cmsecach.c - Use macro instead of "64" magic 2008-09-07 09:28:37 +00:00
cmsysini.c [NTOS]: Implement Configuration Manager routines for building a driver list, sorting it, detecting circular dependencies and ordering, combining groups, tags, group orders and tag orders, etc. Replaces the "drvrlist" I/O interface currently in ReactOS. 2010-04-03 07:44:38 +00:00
cmvalche.c Use memory wrappers instead of ExAllocatePool/ExFreePool directly 2009-08-30 19:20:30 +00:00
cmvalue.c Use memory wrappers instead of ExAllocatePool/ExFreePool directly 2009-08-30 19:20:30 +00:00
cmwraprs.c Merge from amd64-branch: 2010-01-13 22:35:43 +00:00
ntapi.c [ARM]: Fix the ARM build, hopefully without breaking the x86 build in the process. Sorry buds! 2010-02-01 03:51:45 +00:00