Merge pull request #2562 from jeremyd2019/msys2-runtime-getprocaddr-update
msys2-runtime: update patch for getprocaddr
This commit is contained in:
305
msys2-runtime/0044-getprocaddr-refactor-cleanup.patch
Normal file
305
msys2-runtime/0044-getprocaddr-refactor-cleanup.patch
Normal file
@@ -0,0 +1,305 @@
|
||||
From a63ea7e338cabc315b58b2356a004c8772ac0f6c Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Drake <github@jdrake.com>
|
||||
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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user