Reactos

[KMTESTS:PS] Write some tests for process quota management

+136
+1
modules/rostests/kmtests/CMakeLists.txt
··· 94 94 ntos_ob/ObTypes.c 95 95 ntos_ob/ObWait.c 96 96 ntos_ps/PsNotify.c 97 + ntos_ps/PsQuota.c 97 98 ntos_se/SeHelpers.c 98 99 ntos_se/SeInheritance.c 99 100 ntos_se/SeLogonSession.c
+2
modules/rostests/kmtests/kmtest_drv/testlist.c
··· 63 63 KMT_TESTFUNC Test_ObTypeNoClean; 64 64 KMT_TESTFUNC Test_ObTypes; 65 65 KMT_TESTFUNC Test_PsNotify; 66 + KMT_TESTFUNC Test_PsQuota; 66 67 KMT_TESTFUNC Test_SeInheritance; 67 68 KMT_TESTFUNC Test_SeLogonSession; 68 69 KMT_TESTFUNC Test_SeQueryInfoToken; ··· 142 143 { "-ObTypeNoClean", Test_ObTypeNoClean }, 143 144 { "ObTypes", Test_ObTypes }, 144 145 { "PsNotify", Test_PsNotify }, 146 + { "PsQuota", Test_PsQuota }, 145 147 { "RtlAvlTreeKM", Test_RtlAvlTree }, 146 148 { "RtlExceptionKM", Test_RtlException }, 147 149 { "RtlIntSafeKM", Test_RtlIntSafe },
+133
modules/rostests/kmtests/ntos_ps/PsQuota.c
··· 1 + /* 2 + * PROJECT: ReactOS kernel-mode tests 3 + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 + * PURPOSE: Kernel mode tests for process quotas 5 + * COPYRIGHT: Copyright 2021 George Bișoc <george.bisoc@reactos.org> 6 + */ 7 + 8 + #include <kmt_test.h> 9 + 10 + START_TEST(PsQuota) 11 + { 12 + NTSTATUS Status; 13 + VM_COUNTERS VmCounters; 14 + QUOTA_LIMITS QuotaLimits; 15 + SIZE_T NonPagedUsage, PagedUsage; 16 + PEPROCESS Process = PsGetCurrentProcess(); 17 + 18 + /* Guard the quota operations in a guarded region */ 19 + KeEnterGuardedRegion(); 20 + 21 + /* Report the current process' quota limits */ 22 + Status = ZwQueryInformationProcess(NtCurrentProcess(), 23 + ProcessQuotaLimits, 24 + &QuotaLimits, 25 + sizeof(QuotaLimits), 26 + NULL); 27 + if (skip(NT_SUCCESS(Status), "Failed to query quota limits -- %lx\n", Status)) 28 + { 29 + return; 30 + } 31 + 32 + trace("Process paged pool quota limit -- %lu\n", QuotaLimits.PagedPoolLimit); 33 + trace("Process non paged pool quota limit -- %lu\n", QuotaLimits.NonPagedPoolLimit); 34 + trace("Process page file quota limit -- %lu\n\n", QuotaLimits.PagefileLimit); 35 + 36 + /* Query the quota usage */ 37 + Status = ZwQueryInformationProcess(NtCurrentProcess(), 38 + ProcessVmCounters, 39 + &VmCounters, 40 + sizeof(VmCounters), 41 + NULL); 42 + if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 43 + { 44 + return; 45 + } 46 + 47 + /* Test that quotas usage are within limits */ 48 + ok(VmCounters.QuotaNonPagedPoolUsage < QuotaLimits.NonPagedPoolLimit, "Non paged quota over limits (usage -> %lu || limit -> %lu)\n", 49 + VmCounters.QuotaNonPagedPoolUsage, QuotaLimits.NonPagedPoolLimit); 50 + ok(VmCounters.QuotaPagedPoolUsage < QuotaLimits.PagedPoolLimit, "Paged quota over limits (usage -> %lu || limit -> %lu)\n", 51 + VmCounters.QuotaPagedPoolUsage, QuotaLimits.PagedPoolLimit); 52 + 53 + /* Cache the quota usage pools for later checks */ 54 + NonPagedUsage = VmCounters.QuotaNonPagedPoolUsage; 55 + PagedUsage = VmCounters.QuotaPagedPoolUsage; 56 + 57 + /* Charge some paged and non paged quotas */ 58 + Status = PsChargeProcessNonPagedPoolQuota(Process, 0x200); 59 + ok_irql(PASSIVE_LEVEL); 60 + ok_eq_hex(Status, STATUS_SUCCESS); 61 + 62 + Status = PsChargeProcessPagedPoolQuota(Process, 0x500); 63 + ok_irql(PASSIVE_LEVEL); 64 + ok_eq_hex(Status, STATUS_SUCCESS); 65 + 66 + /* Query the quota usage again */ 67 + Status = ZwQueryInformationProcess(NtCurrentProcess(), 68 + ProcessVmCounters, 69 + &VmCounters, 70 + sizeof(VmCounters), 71 + NULL); 72 + if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 73 + { 74 + return; 75 + } 76 + 77 + 78 + /* Test again the usage that's within limits */ 79 + ok(VmCounters.QuotaNonPagedPoolUsage < QuotaLimits.NonPagedPoolLimit, "Non paged quota over limits (usage -> %lu || limit -> %lu)\n", 80 + VmCounters.QuotaNonPagedPoolUsage, QuotaLimits.NonPagedPoolLimit); 81 + ok(VmCounters.QuotaPagedPoolUsage < QuotaLimits.PagedPoolLimit, "Paged quota over limits (usage -> %lu || limit -> %lu)\n", 82 + VmCounters.QuotaPagedPoolUsage, QuotaLimits.PagedPoolLimit); 83 + 84 + /* 85 + * Make sure the results are consistent, that nobody else 86 + * is charging quotas other than us. 87 + */ 88 + ok_eq_size(VmCounters.QuotaNonPagedPoolUsage, NonPagedUsage + 0x200); 89 + ok_eq_size(VmCounters.QuotaPagedPoolUsage, PagedUsage + 0x500); 90 + 91 + /* Report the quota usage */ 92 + trace("=== QUOTA USAGE AFTER CHARGE ===\n\n"); 93 + trace("Process paged pool quota usage -- %lu\n", VmCounters.QuotaPagedPoolUsage); 94 + trace("Process paged pool quota peak -- %lu\n", VmCounters.QuotaPeakPagedPoolUsage); 95 + trace("Process non paged pool quota usage -- %lu\n", VmCounters.QuotaNonPagedPoolUsage); 96 + trace("Process non paged pool quota peak -- %lu\n", VmCounters.QuotaPeakNonPagedPoolUsage); 97 + trace("Process page file quota usage -- %lu\n", VmCounters.PagefileUsage); 98 + trace("Process page file quota peak -- %lu\n\n", VmCounters.PeakPagefileUsage); 99 + 100 + /* Return the quotas we've charged up */ 101 + PsReturnProcessNonPagedPoolQuota(Process, 0x200); 102 + PsReturnProcessPagedPoolQuota(Process, 0x500); 103 + 104 + /* Query the quota usage again */ 105 + Status = ZwQueryInformationProcess(NtCurrentProcess(), 106 + ProcessVmCounters, 107 + &VmCounters, 108 + sizeof(VmCounters), 109 + NULL); 110 + if (skip(NT_SUCCESS(Status), "Failed to query quota usage -- %lx\n", Status)) 111 + { 112 + return; 113 + } 114 + 115 + /* 116 + * Check that nobody else has returned quotas 117 + * but only us. 118 + */ 119 + ok_eq_size(VmCounters.QuotaNonPagedPoolUsage, NonPagedUsage); 120 + ok_eq_size(VmCounters.QuotaPagedPoolUsage, PagedUsage); 121 + 122 + /* Report the usage again */ 123 + trace("=== QUOTA USAGE AFTER RETURN ===\n\n"); 124 + trace("Process paged pool quota usage -- %lu\n", VmCounters.QuotaPagedPoolUsage); 125 + trace("Process paged pool quota peak -- %lu\n", VmCounters.QuotaPeakPagedPoolUsage); 126 + trace("Process non paged pool quota usage -- %lu\n", VmCounters.QuotaNonPagedPoolUsage); 127 + trace("Process non paged pool quota peak -- %lu\n", VmCounters.QuotaPeakNonPagedPoolUsage); 128 + trace("Process page file quota usage -- %lu\n", VmCounters.PagefileUsage); 129 + trace("Process page file quota peak -- %lu\n\n", VmCounters.PeakPagefileUsage); 130 + 131 + /* We're done, leave the region */ 132 + KeLeaveGuardedRegion(); 133 + }