Windows: rewrite process enumeration around NtQuerySystemInformation - #967
Open
CarterLi wants to merge 4 commits into
Open
Windows: rewrite process enumeration around NtQuerySystemInformation#967CarterLi wants to merge 4 commits into
CarterLi wants to merge 4 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: I made the high-level design, and let AI write the code (with my small fixes here and there). It's still carefully tested and benchmarked.
Summary
Rewrites the Windows process backend around a single
NtQuerySystemInformation(NQSI) snapshot, replacing the previous per-processOpenProcess→GetProcessTimes/GetProcessMemoryInfo/GetProcessIoCounters/GetPriorityClass/EnumProcessModulesExwalk. This cuts the syscall count from O(N × k) to O(1) for the enumeration phase and eliminates the race window where a process could exit between individual queries.Changes
Performance
LookupAccountSidWis deferred to column render time (SID_MAX::display_name()) and cached per SID value, instead of being called eagerly for every process during collection. This saves several milliseconds when many groups are present (especially for system processes).SystemFullProcessInformation(class 148) is used. It embeds each process's user SID directly in the snapshot, saving oneOpenProcessToken+GetTokenInformationround-trip per process.Correctness / bug fixes
command,start_time,cpu_info,memory_info,disk_info,user,groups,thread) to be non-None(all_okgate); anyOpenProcessfailure (e.g.System,Registry,Memory Compression) caused the entire entry to be skipped. NQSI returns memory, CPU, I/O and image name for all processes including kernel threads, so they are now always listed. User / Group columns are left empty when the token cannot be opened.OpenProcessTokenhandles were never closed inget_user/get_groups/set_privilege. Process handles are now managed by aProcHandlesRAII wrapper with aDropimpl.HashMap<PSID, _>cache was keyed by the address of a transient allocation; once freed, the address could be recycled by the next query and return a different account's name. The cache is now keyed bySID_MAX(an owned, fixed-size 68-byte SID) with value equality.NtQueryInformationProcess(ProcessCommandLineInformation)instead ofEnumProcessModulesEx+GetModuleBaseNameW, which only returned the bare executable name. Fixes Running in windows it does not show command line arguments #752.Other
SID_MAXvalue type. SIDs are stored as a fixed-size#[repr(C)]struct (embedding the officialSIDheader + padding toSECURITY_MAX_SID_SIZE) instead ofVec<u64>, removing per-SID heap allocations and enablingHash/Eqby live bytes.GlobalMemoryStatusEx(ullTotalPhys) instead ofGetPerformanceInfo(PhysicalTotal × PageSize). This reduced one system DLL dependency after the previousEnumProcessModulesEx,GetModuleBaseNameWandGetPerformanceInforemoval.Behavior changes
Normal,Idle,High, …) viaGetPriorityClasssvchost.exe)C:\Windows\System32\svchost.exe -k netsvcs), falling back to the image name when the process cannot be opened.show_kthreadis set to false.Screenshots
Before, with or without admin permission
After, without admin permission
After, with admin permission
Benchmark
Despite
procs.new.exereports about 2x more processes thanprocs.old.exeNote
NtQuerySystemInformationandNtQueryInformationProcessare so calledNative API, which are partially documented only. This PR does use some undocumented features.My original PR message if you prefer
NtQuerySystemInformation(NQSI) snapshot instead of the previous per-process handle/token/module walk. This greatly reduced syscalls (GetProcessMemoryInfo,GetProcessTimes,GetProcessIoCounters,GetPriorityClass,EnumProcessModulesEx) per process, and therefore improved performance and reduced risks that processes may exit between syscalls.NtQueryInformationProcess(ProcessCommandLineInformation)for processes we have permission to open. Fixes Running in windows it does not show command line arguments #752