diff options
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/windows-nat.c | 115 | ||||
-rw-r--r-- | gdb/nat/windows-nat.h | 38 |
2 files changed, 149 insertions, 4 deletions
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index 8048344..e52da16 100644 --- a/gdb/nat/windows-nat.c +++ b/gdb/nat/windows-nat.c @@ -69,6 +69,10 @@ GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent; typedef HRESULT WINAPI (GetThreadDescription_ftype) (HANDLE, PWSTR *); static GetThreadDescription_ftype *GetThreadDescription; +InitializeProcThreadAttributeList_ftype *InitializeProcThreadAttributeList; +UpdateProcThreadAttribute_ftype *UpdateProcThreadAttribute; +DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList; + /* Note that 'debug_events' must be locally defined in the relevant functions. */ #define DEBUG_EVENTS(fmt, ...) \ @@ -741,15 +745,104 @@ wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout) return result; } -/* Helper template for the CreateProcess wrappers. */ +/* Flags to pass to UpdateProcThreadAttribute. */ +#define relocate_aslr_flags ((0x2 << 8) | (0x2 << 16)) + +/* Attribute to pass to UpdateProcThreadAttribute. */ +#define mitigation_policy 0x00020007 + +/* Pick one of the symbols as a sentinel. */ +#ifdef PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF + +static_assert ((PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF + | PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_OFF) + == relocate_aslr_flags, + "check that ASLR flag values are correct"); + +static_assert (PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY == mitigation_policy, + "check that mitigation policy value is correct"); + +#endif + +/* Helper template for the CreateProcess wrappers. + + FUNC is the type of the underlying CreateProcess call. CHAR is the + character type to use, and INFO is the "startupinfo" type to use. + + DO_CREATE_PROCESS is the underlying CreateProcess function to use; + the remaining arguments are passed to it. */ template<typename FUNC, typename CHAR, typename INFO> BOOL create_process_wrapper (FUNC *do_create_process, const CHAR *image, CHAR *command_line, DWORD flags, void *environment, const CHAR *cur_dir, + bool no_randomization, INFO *startup_info, PROCESS_INFORMATION *process_info) { + if (no_randomization && disable_randomization_available ()) + { + static bool tried_and_failed; + + if (!tried_and_failed) + { + /* Windows 8 is required for the real declaration, but to + allow building on earlier versions of Windows, we declare + the type locally. */ + struct gdb_extended_info + { + INFO StartupInfo; + gdb_lpproc_thread_attribute_list lpAttributeList; + }; + + gdb_extended_info info_ex {}; + + if (startup_info != nullptr) + info_ex.StartupInfo = *startup_info; + info_ex.StartupInfo.cb = sizeof (info_ex); + SIZE_T size = 0; + /* Ignore the result here. The documentation says the first + call always fails, by design. */ + InitializeProcThreadAttributeList (nullptr, 1, 0, &size); + info_ex.lpAttributeList + = (PPROC_THREAD_ATTRIBUTE_LIST) alloca (size); + InitializeProcThreadAttributeList (info_ex.lpAttributeList, + 1, 0, &size); + + gdb::optional<BOOL> return_value; + DWORD attr_flags = relocate_aslr_flags; + if (!UpdateProcThreadAttribute (info_ex.lpAttributeList, 0, + mitigation_policy, + &attr_flags, + sizeof (attr_flags), + nullptr, nullptr)) + tried_and_failed = true; + else + { + BOOL result = do_create_process (image, command_line, + nullptr, nullptr, + TRUE, + (flags + | EXTENDED_STARTUPINFO_PRESENT), + environment, + cur_dir, + (STARTUPINFO *) &info_ex, + process_info); + if (result) + return_value = result; + else if (GetLastError () == ERROR_INVALID_PARAMETER) + tried_and_failed = true; + else + return_value = FALSE; + } + + DeleteProcThreadAttributeList (info_ex.lpAttributeList); + + if (return_value.has_value ()) + return *return_value; + } + } + return do_create_process (image, command_line, /* command line */ nullptr, /* Security */ @@ -767,11 +860,12 @@ create_process_wrapper (FUNC *do_create_process, const CHAR *image, BOOL create_process (const char *image, char *command_line, DWORD flags, void *environment, const char *cur_dir, + bool no_randomization, STARTUPINFOA *startup_info, PROCESS_INFORMATION *process_info) { return create_process_wrapper (CreateProcessA, image, command_line, flags, - environment, cur_dir, + environment, cur_dir, no_randomization, startup_info, process_info); } @@ -782,11 +876,12 @@ create_process (const char *image, char *command_line, DWORD flags, BOOL create_process (const wchar_t *image, wchar_t *command_line, DWORD flags, void *environment, const wchar_t *cur_dir, + bool no_randomization, STARTUPINFOW *startup_info, PROCESS_INFORMATION *process_info); { return create_process_wrapper (CreateProcessW, image, command_line, flags, - environment, cur_dir, + environment, cur_dir, no_randomization, startup_info, process_info); } @@ -827,6 +922,16 @@ bad_GetConsoleFontSize (HANDLE w, DWORD nFont) /* See windows-nat.h. */ bool +disable_randomization_available () +{ + return (InitializeProcThreadAttributeList != nullptr + && UpdateProcThreadAttribute != nullptr + && DeleteProcThreadAttributeList != nullptr); +} + +/* See windows-nat.h. */ + +bool initialize_loadable () { bool result = true; @@ -852,6 +957,10 @@ initialize_loadable () #endif GPA (hm, GenerateConsoleCtrlEvent); GPA (hm, GetThreadDescription); + + GPA (hm, InitializeProcThreadAttributeList); + GPA (hm, UpdateProcThreadAttribute); + GPA (hm, DeleteProcThreadAttributeList); } /* Set variables to dummy versions of these processes if the function diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h index d8c498e..65b789f 100644 --- a/gdb/nat/windows-nat.h +++ b/gdb/nat/windows-nat.h @@ -294,17 +294,21 @@ extern BOOL continue_last_debug_event (DWORD continue_status, extern BOOL wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout); -/* Wrappers for CreateProcess. */ +/* Wrappers for CreateProcess. These exist primarily so that the + "disable randomization" feature can be implemented in a single + place. */ extern BOOL create_process (const char *image, char *command_line, DWORD flags, void *environment, const char *cur_dir, + bool no_randomization, STARTUPINFOA *startup_info, PROCESS_INFORMATION *process_info); #ifdef __CYGWIN__ extern BOOL create_process (const wchar_t *image, wchar_t *command_line, DWORD flags, void *environment, const wchar_t *cur_dir, + bool no_randomization, STARTUPINFOW *startup_info, PROCESS_INFORMATION *process_info); #endif /* __CYGWIN__ */ @@ -313,10 +317,15 @@ extern BOOL create_process (const wchar_t *image, wchar_t *command_line, #define DebugActiveProcessStop dyn_DebugActiveProcessStop #define DebugBreakProcess dyn_DebugBreakProcess #define DebugSetProcessKillOnExit dyn_DebugSetProcessKillOnExit +#undef EnumProcessModules #define EnumProcessModules dyn_EnumProcessModules +#undef EnumProcessModulesEx #define EnumProcessModulesEx dyn_EnumProcessModulesEx +#undef GetModuleInformation #define GetModuleInformation dyn_GetModuleInformation +#undef GetModuleFileNameExA #define GetModuleFileNameExA dyn_GetModuleFileNameExA +#undef GetModuleFileNameExW #define GetModuleFileNameExW dyn_GetModuleFileNameExW #define LookupPrivilegeValueA dyn_LookupPrivilegeValueA #define OpenProcessToken dyn_OpenProcessToken @@ -327,6 +336,9 @@ extern BOOL create_process (const wchar_t *image, wchar_t *command_line, #define Wow64SetThreadContext dyn_Wow64SetThreadContext #define Wow64GetThreadSelectorEntry dyn_Wow64GetThreadSelectorEntry #define GenerateConsoleCtrlEvent dyn_GenerateConsoleCtrlEvent +#define InitializeProcThreadAttributeList dyn_InitializeProcThreadAttributeList +#define UpdateProcThreadAttribute dyn_UpdateProcThreadAttribute +#define DeleteProcThreadAttributeList dyn_DeleteProcThreadAttributeList typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL, PTOKEN_PRIVILEGES, @@ -397,6 +409,30 @@ extern Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry; typedef BOOL WINAPI (GenerateConsoleCtrlEvent_ftype) (DWORD, DWORD); extern GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent; +/* We use a local typedef for this type to avoid depending on + Windows 8. */ +typedef void *gdb_lpproc_thread_attribute_list; + +typedef BOOL WINAPI (InitializeProcThreadAttributeList_ftype) + (gdb_lpproc_thread_attribute_list lpAttributeList, + DWORD dwAttributeCount, DWORD dwFlags, PSIZE_T lpSize); +extern InitializeProcThreadAttributeList_ftype *InitializeProcThreadAttributeList; + +typedef BOOL WINAPI (UpdateProcThreadAttribute_ftype) + (gdb_lpproc_thread_attribute_list lpAttributeList, + DWORD dwFlags, DWORD_PTR Attribute, PVOID lpValue, SIZE_T cbSize, + PVOID lpPreviousValue, PSIZE_T lpReturnSize); +extern UpdateProcThreadAttribute_ftype *UpdateProcThreadAttribute; + +typedef void WINAPI (DeleteProcThreadAttributeList_ftype) + (gdb_lpproc_thread_attribute_list lpAttributeList); +extern DeleteProcThreadAttributeList_ftype *DeleteProcThreadAttributeList; + +/* Return true if it's possible to disable randomization on this + host. */ + +extern bool disable_randomization_available (); + /* Load any functions which may not be available in ancient versions of Windows. */ |