diff options
-rw-r--r-- | gdb/NEWS | 2 | ||||
-rw-r--r-- | gdb/nat/windows-nat.c | 115 | ||||
-rw-r--r-- | gdb/nat/windows-nat.h | 38 | ||||
-rw-r--r-- | gdb/windows-nat.c | 7 | ||||
-rw-r--r-- | gdbserver/win32-low.cc | 1 | ||||
-rw-r--r-- | gdbserver/win32-low.h | 5 |
6 files changed, 164 insertions, 4 deletions
@@ -71,6 +71,8 @@ maintenance info line-table Python 2. From GDB 13, it will only be possible to build GDB itself with Python 3 support. +* The disable-randomization setting now works on Windows. + * Improved C++ template support GDB now treats functions/types involving C++ templates like it does function 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. */ diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 262619d..0f9fde9 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -281,6 +281,11 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target> int get_windows_debug_event (int pid, struct target_waitstatus *ourstatus); void do_initial_windows_stuff (DWORD pid, bool attaching); + + bool supports_disable_randomization () override + { + return disable_randomization_available (); + } }; static windows_nat_target the_windows_nat_target; @@ -2493,6 +2498,7 @@ windows_nat_target::create_inferior (const char *exec_file, windows_init_thread_list (); ret = create_process (args, flags, w32_env, inferior_cwd != nullptr ? infcwd : nullptr, + disable_randomization, &si, &pi); if (w32_env) /* Just free the Win32 environment, if it could be created. */ @@ -2612,6 +2618,7 @@ windows_nat_target::create_inferior (const char *exec_file, flags, /* start flags */ w32env, /* environment */ inferior_cwd, /* current directory */ + disable_randomization, &si, &pi); if (tty != INVALID_HANDLE_VALUE) diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc index 00ce2a5..a9af646 100644 --- a/gdbserver/win32-low.cc +++ b/gdbserver/win32-low.cc @@ -586,6 +586,7 @@ create_process (const char *program, char *args, (inferior_cwd.empty () ? NULL : gdb_tilde_expand (inferior_cwd.c_str ()).c_str()), + get_client_state ().disable_randomization, &si, /* start info */ pi); /* proc info */ diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h index d16f1f9..b29e8b3 100644 --- a/gdbserver/win32-low.h +++ b/gdbserver/win32-low.h @@ -165,6 +165,11 @@ public: { return true; } const char *pid_to_exec_file (int pid) override; + + bool supports_disable_randomization () override + { + return windows_nat::disable_randomization_available (); + } }; /* The sole Windows process. */ |