From 1decd130547a2956f420239705574f837419d0d5 Mon Sep 17 00:00:00 2001 From: Jeremy Drake Date: Fri, 25 Jun 2021 00:20:28 -0700 Subject: [PATCH] msys2-runtime: update patch for getprocaddr --- .../0044-getprocaddr-refactor-cleanup.patch | 305 ++++++++++++++++++ msys2-runtime/PKGBUILD | 11 +- 2 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 msys2-runtime/0044-getprocaddr-refactor-cleanup.patch diff --git a/msys2-runtime/0044-getprocaddr-refactor-cleanup.patch b/msys2-runtime/0044-getprocaddr-refactor-cleanup.patch new file mode 100644 index 00000000..34fe2dae --- /dev/null +++ b/msys2-runtime/0044-getprocaddr-refactor-cleanup.patch @@ -0,0 +1,305 @@ +From a63ea7e338cabc315b58b2356a004c8772ac0f6c Mon Sep 17 00:00:00 2001 +From: Jeremy Drake +Date: Tue, 22 Jun 2021 22:06:26 -0700 +Subject: [PATCH 44/N] getprocaddr: refactor/cleanup + +Look in kernel32 and kernelbase for CtrlRoutine before breaking out the +big guns and trying to find it in the call stack. Fixes #51. + +The change to look at the return code of the thread caused the program +to act as though ExitProcess failed to inject. Deal with this by +passing the thread exit code as an OUT param, and only looking at it +when calling the CtrlRoutine. + +While I was there, I noticed a potential race between CreateEvent and +the ctrl_handler function that uses it, so cleaned that up. Also the +event doesn't need to be named, so don't name it to avoid potential +collisions with other processes. + +Fixed a couple of printf type warnings. As this is mingw, it should be +safe to use %lu for DWORDs. +--- + winsup/utils/getprocaddr.c | 202 +++++++++++++++++++++---------------- + 1 file changed, 116 insertions(+), 86 deletions(-) + +diff --git a/winsup/utils/getprocaddr.c b/winsup/utils/getprocaddr.c +index d5ecd35..25814c7 100644 +--- a/winsup/utils/getprocaddr.c ++++ b/winsup/utils/getprocaddr.c +@@ -27,13 +27,14 @@ static HANDLE CtrlEvent; + static int + inject_remote_thread_into_process (HANDLE process, + LPTHREAD_START_ROUTINE address, +- uintptr_t exit_code) ++ uintptr_t exit_code, ++ DWORD *thread_return) + { + int res = -1; + + if (!address) + return res; +- DWORD thread_id, code; ++ DWORD thread_id; + HANDLE thread = CreateRemoteThread (process, NULL, 1024 * 1024, address, + (PVOID)exit_code, 0, &thread_id); + if (thread) +@@ -53,9 +54,8 @@ inject_remote_thread_into_process (HANDLE process, + CtrlEvent set by SetConsoleCtrlHandler is handled correctly, in all + other cases it returns something non-zero(not sure what it that). + */ +- GetExitCodeThread (thread, &code); +- if (code != 0) +- res = code; ++ if (thread_return != NULL) ++ GetExitCodeThread (thread, thread_return); + + CloseHandle (thread); + } +@@ -80,6 +80,7 @@ ctrl_handler (DWORD ctrl_type) + HANDLE process; + PSYMBOL_INFOW info; + DWORD64 displacement; ++ DWORD thread_return = 0; + + count = CaptureStackBackTrace (1l /* skip this function */, + 1l /* return only one trace item */, &address, +@@ -134,15 +135,18 @@ ctrl_handler (DWORD ctrl_type) + return 1; + } + /* Inject the remote thread only when asked to */ +- int t = inject_remote_thread_into_process (h, address, exit_code); +- if (t != 0) ++ if (inject_remote_thread_into_process (h, address, exit_code, ++ &thread_return) < 0) + { + fprintf (stderr, +- "Error while injecting remote thread %d for pid(%d)\n", t, +- pid); ++ "Error while injecting remote thread for pid(%lu)\n", pid); + exit (1); /*We should exit immediately or else there will a 10s hang + waiting for the event to happen.*/ + } ++ if (thread_return) ++ fprintf (stderr, ++ "Injected remote thread for pid(%lu) returned %lu\n", pid, ++ thread_return); + } + SymCleanup (process); + if (!SetEvent (CtrlEvent)) +@@ -150,77 +154,16 @@ ctrl_handler (DWORD ctrl_type) + fprintf (stderr, "SetEvent failed (%ld)\n", GetLastError ()); + return 1; + } +- exit (0); ++ exit (thread_return != 0); + } + +-int +-main (int argc, char **argv) ++/* The easy route for finding the address of CtrlRoutine ++ * would be use GetProcAddress() but this isn't viable ++ * here because that symbol isn't exported. ++ */ ++static int ++find_ctrl_routine_the_hard_way () + { +- char *end; +- +- if (argc == 4) +- { +- exit_code = atoi (argv[2]); +- pid = strtoul (argv[3], NULL, 0); +- } +- else if (argc == 2) +- { +- pid = 0; +- } +- else +- { +- fprintf (stderr, "Need a function name, exit code and pid\n" +- "Or needs a function name.\n"); +- return 1; +- } +- +- /* The easy route for finding the address of CtrlRoutine +- * would be use GetProcAddress() but this isn't viable +- * because here because that symbol isn't exported. +- */ +- +- if (strcmp (argv[1], "CtrlRoutine")) +- { +- HINSTANCE kernel32 = GetModuleHandle ("kernel32"); +- if (!kernel32) +- return 1; +- void *address = (void *)GetProcAddress (kernel32, argv[1]); +- +- if (!address) +- { +- fprintf (stderr, "Could not find address in stack\n"); +- return 1; +- } +- +- if (pid == 0) +- { +- printf ("%p\n", address); +- fflush (stdout); +- return 0; +- } +- HANDLE h = OpenProcess (PROCESS_CREATE_THREAD | +- PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | +- PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); +- if (h == NULL) +- { +- fprintf (stderr, "OpenProcess failed: %ld\n", GetLastError ()); +- return 1; +- } +- /* Inject the remote thread */ +- if (inject_remote_thread_into_process (h, (LPTHREAD_START_ROUTINE)address, +- exit_code) < 0) +- { +- fprintf (stderr, "Could not inject thread into process %d\n", pid); +- return 1; +- } +- return 0; +- } +- if (argc > 4) +- { +- fprintf (stderr, "Unhandled option: %s\n", argv[4]); +- return 1; +- } +- + /* + * Avoid terminating all processes attached to the current console; + * This would happen if we used the same console as the caller, though, +@@ -249,32 +192,119 @@ main (int argc, char **argv) + } + } + ++ CtrlEvent = CreateEvent (NULL, // default security attributes ++ TRUE, // manual-reset event ++ FALSE, // initial state is nonsignaled ++ NULL // object name ++ ); ++ ++ if (CtrlEvent == NULL) ++ { ++ fprintf (stderr, "CreateEvent failed (%ld)\n", GetLastError ()); ++ return 1; ++ } ++ ++ + if (!SetConsoleCtrlHandler (ctrl_handler, TRUE)) + { + fprintf (stderr, "Could not register Ctrl handler\n"); + return 1; + } ++ + if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, 0)) + { + fprintf (stderr, "Could not simulate Ctrl+Break\n"); + return 1; + } + +- CtrlEvent = CreateEvent (NULL, // default security attributes +- TRUE, // manual-reset event +- FALSE, // initial state is nonsignaled +- TEXT ("CtrlEvent") // object name +- ); +- if (CtrlEvent == NULL) ++ if (WaitForSingleObject (CtrlEvent, 10000 /* 10 seconds*/) != WAIT_OBJECT_0) + { +- fprintf (stderr, "CreateEvent failed (%ld)\n", GetLastError ()); ++ fprintf (stderr, "WaitForSingleObject failed (%ld)\n", GetLastError ()); + return 1; + } ++ return 0; ++} + +- if (WaitForSingleObject (CtrlEvent, 10000 /* 10 seconds*/) != WAIT_OBJECT_0) ++static void * ++get_proc_addr (const char * module_name, const char * function_name) ++{ ++ HMODULE module = GetModuleHandle (module_name); ++ if (!module) ++ return NULL; ++ return (void *)GetProcAddress (module, function_name); ++} ++ ++int ++main (int argc, char **argv) ++{ ++ char *end; ++ void *address; ++ BOOL is_ctrl_routine; ++ DWORD thread_return = 0; ++ ++ if (argc == 4) + { +- fprintf (stderr, "WaitForSingleObject failed (%ld)\n", GetLastError ()); ++ exit_code = atoi (argv[2]); ++ pid = strtoul (argv[3], NULL, 0); ++ } ++ else if (argc == 2) ++ { ++ pid = 0; ++ } ++ else ++ { ++ fprintf (stderr, "Need a function name, exit code and pid\n" ++ "Or needs a function name.\n"); ++ return 1; ++ } ++ ++ is_ctrl_routine = strcmp (argv[1], "CtrlRoutine") == 0; ++ address = get_proc_addr ("kernel32", argv[1]); ++ if (is_ctrl_routine && !address) ++ { ++ /* CtrlRoutine is undocumented, and has been seen in both ++ * kernel32 and kernelbase ++ */ ++ address = get_proc_addr ("kernelbase", argv[1]); ++ if (!address) ++ return find_ctrl_routine_the_hard_way (); ++ } ++ ++ if (!address) ++ { ++ fprintf (stderr, "Could not get proc address\n"); ++ return 1; ++ } ++ ++ if (pid == 0) ++ { ++ printf ("%p\n", address); ++ fflush (stdout); ++ return 0; ++ } ++ HANDLE h = OpenProcess (PROCESS_CREATE_THREAD | ++ PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | ++ PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); ++ if (h == NULL) ++ { ++ fprintf (stderr, "OpenProcess failed: %ld\n", GetLastError ()); ++ return 1; ++ } ++ /* Inject the remote thread */ ++ if (inject_remote_thread_into_process (h, (LPTHREAD_START_ROUTINE)address, ++ exit_code, &thread_return) < 0) ++ { ++ fprintf (stderr, "Could not inject thread into process %lu\n", pid); + return 1; + } ++ ++ if (is_ctrl_routine && thread_return) ++ { ++ fprintf (stderr, ++ "Injected remote thread for pid %lu returned %lu\n", pid, ++ thread_return); ++ return 1; ++ } ++ + return 0; + } +-- +2.32.0.windows.1 + diff --git a/msys2-runtime/PKGBUILD b/msys2-runtime/PKGBUILD index 4e0d35c8..b28dcc06 100644 --- a/msys2-runtime/PKGBUILD +++ b/msys2-runtime/PKGBUILD @@ -4,7 +4,7 @@ pkgbase=msys2-runtime pkgname=('msys2-runtime' 'msys2-runtime-devel') pkgver=3.2.0 -pkgrel=12 +pkgrel=13 pkgdesc="Cygwin POSIX emulation engine" arch=('i686' 'x86_64') url="https://www.cygwin.com/" @@ -65,7 +65,8 @@ source=('msys2-runtime'::git://sourceware.org/git/newlib-cygwin.git#tag=cygwin-$ 0040-Emulate-GenerateConsoleCtrlEvent-upon-Ctrl-C.patch 0041-kill-kill-Win32-processes-more-gently.patch 0042-Fix-64-vs-32-bit-type-confusion-in-swprintf.patch - 0043-Don-t-fall-back-to-ExitProcess-if-process-handled-Ct.patch) + 0043-Don-t-fall-back-to-ExitProcess-if-process-handled-Ct.patch + 0044-getprocaddr-refactor-cleanup.patch) sha256sums=('SKIP' '605f3f31dcca983fad2659f2d8f3531217e3f133757b40b0977e6a17c406c147' '5d120d24ce55ef08bf459781610e32c4a8e5e0eac73971a60e80590c6432d940' @@ -109,7 +110,8 @@ sha256sums=('SKIP' '460adc6de940e25332efec7a6615bb95088ae0652870a1c0b4f37c72671444fe' 'cc0bfded281675af09ce94d847e814f77fd5cbcd86b09b7436a0e91b7697b8f4' '04ee4b9ca58bfa8a3c0370d1cecadf50c9c02daf6a4e5ccd4610336155538b71' - '34f9a822fd2cbfd3a556f30ccea6f1dd6bb66b9edf0cd506c0cbb69b6ae437d7') + '34f9a822fd2cbfd3a556f30ccea6f1dd6bb66b9edf0cd506c0cbb69b6ae437d7' + '54dd5a62e0b9491ed3d1e2ac934297864001c0d6751723342c92a332f105d603') # Helper macros to help make tasks easier # apply_patch_with_msg() { @@ -189,7 +191,8 @@ prepare() { 0040-Emulate-GenerateConsoleCtrlEvent-upon-Ctrl-C.patch \ 0041-kill-kill-Win32-processes-more-gently.patch \ 0042-Fix-64-vs-32-bit-type-confusion-in-swprintf.patch \ - 0043-Don-t-fall-back-to-ExitProcess-if-process-handled-Ct.patch + 0043-Don-t-fall-back-to-ExitProcess-if-process-handled-Ct.patch \ + 0044-getprocaddr-refactor-cleanup.patch } build() {