From 98ce3928a99273b631c525a81df022e6f8ec46a7 Mon Sep 17 00:00:00 2001 From: Sven Hoexter Date: Mon, 25 Jul 2022 20:38:38 +0200 Subject: [PATCH] New upstream version 2.1 --- Makefile | 7 +++-- README.md | 10 ++++++- jattach.spec | 6 +++- src/posix/jattach.c | 4 +++ src/posix/jattach_openj9.c | 7 ++++- src/posix/psutil.c | 13 +++++---- src/windows/jattach.c | 59 ++++++++++++++++++++++++++------------ 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 4b04acf..7ff43df 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -JATTACH_VERSION=2.0 +JATTACH_VERSION=2.1 ifneq ($(findstring Windows,$(OS)),) CL=cl.exe @@ -6,13 +6,14 @@ ifneq ($(findstring Windows,$(OS)),) JATTACH_EXE=jattach.exe JATTACH_DLL=jattach.dll else - CFLAGS ?= -O3 JATTACH_EXE=jattach UNAME_S:=$(shell uname -s) ifeq ($(UNAME_S),Darwin) + CFLAGS ?= -O3 -arch x86_64 -arch arm64 -mmacos-version-min=10.12 JATTACH_DLL=libjattach.dylib else + CFLAGS ?= -O3 JATTACH_DLL=libjattach.so endif @@ -38,7 +39,7 @@ build/jattach: src/posix/*.c src/posix/*.h $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DJATTACH_VERSION=\"$(JATTACH_VERSION)\" -o $@ src/posix/*.c build/$(JATTACH_DLL): src/posix/*.c src/posix/*.h - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DJATTACH_VERSION=\"$(JATTACH_VERSION)\" -fPIC -shared -fvisibility=hidden -o $@ src/posix/*.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -fPIC -shared -fvisibility=hidden -o $@ src/posix/*.c build/jattach.exe: src/windows/jattach.c $(CL) $(CFLAGS) /DJATTACH_VERSION=\"$(JATTACH_VERSION)\" /Fobuild/jattach.obj /Fe$@ $^ advapi32.lib /link /SUBSYSTEM:CONSOLE,5.02 diff --git a/README.md b/README.md index 711ffe6..3699451 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ### JVM Dynamic Attach utility -The utility to send commands to remote JVM via Dynamic Attach mechanism. +The utility to send commands to a JVM process via Dynamic Attach mechanism. All-in-one **jmap + jstack + jcmd + jinfo** functionality in a single tiny program. No installed JDK required, works with just JRE. Supports Linux containers. @@ -66,3 +66,11 @@ On Alpine Linux, you can use the following command to install `jattach` package [jattach](https://aur.archlinux.org/packages/jattach/) package can be installed from [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository) using one of [AUR helpers](https://wiki.archlinux.org/index.php/AUR_helpers), e.g., `yay`: $ yay -S jattach + +#### Debian Linux + +On Debian Linux, you can use the following command to install `jattach` from the [official repository](https://packages.debian.org/search?keywords=jattach): + + $ apt install jattach + +Packages are provided for **bullseye** (stable), **bookworm** (testing) and **sid** (unstable). diff --git a/jattach.spec b/jattach.spec index 529cf0e..452ab91 100644 --- a/jattach.spec +++ b/jattach.spec @@ -1,5 +1,5 @@ Name: jattach -Version: 2.0 +Version: 2.1 Release: 1 Summary: JVM Dynamic Attach utility @@ -35,6 +35,10 @@ install -p -m 555 %{_sourcedir}/bin/jattach ${BIN} /usr/bin/jattach %changelog +* Mon Jul 25 2022 Vadim Tsesko - 2.1-1 +- Handle both tabs and spaces when parsing /proc/pid/status +- Socket timeout while reading response from OpenJ9 VM + * Wed Aug 11 2021 Vadim Tsesko - 2.0-1 - Attach to OpenJ9 VMs - Pass agent error codes diff --git a/src/posix/jattach.c b/src/posix/jattach.c index 804d13d..53d9dfb 100644 --- a/src/posix/jattach.c +++ b/src/posix/jattach.c @@ -64,6 +64,8 @@ int jattach(int pid, int argc, char** argv) { } } +#ifdef JATTACH_VERSION + int main(int argc, char** argv) { if (argc < 3) { printf("jattach " JATTACH_VERSION " built on " __DATE__ "\n" @@ -86,3 +88,5 @@ int main(int argc, char** argv) { return jattach(pid, argc - 2, argv + 2); } + +#endif // JATTACH_VERSION diff --git a/src/posix/jattach_openj9.c b/src/posix/jattach_openj9.c index f34f4cc..deab4c6 100644 --- a/src/posix/jattach_openj9.c +++ b/src/posix/jattach_openj9.c @@ -273,7 +273,8 @@ static int write_reply_info(int pid, int port, unsigned long long key) { } int chars = snprintf(path, sizeof(path), "%016llx\n%d\n", key, port); - write(fd, path, chars); + ssize_t r = write(fd, path, chars); + (void)r; close(fd); return 0; @@ -327,6 +328,10 @@ static int accept_client(int s, unsigned long long key) { return -1; } + // Reset the timeout, as the command execution may take arbitrary long time + struct timeval tv0 = {0, 0}; + setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &tv0, sizeof(tv0)); + return client; } diff --git a/src/posix/psutil.c b/src/posix/psutil.c index 847a060..9beea88 100644 --- a/src/posix/psutil.c +++ b/src/posix/psutil.c @@ -129,15 +129,18 @@ int get_process_info(int pid, uid_t* uid, gid_t* gid, int* nspid) { int nspid_found = 0; while (getline(&line, &size, status_file) != -1) { - if (strncmp(line, "Uid:", 4) == 0) { + if (strncmp(line, "Uid:", 4) == 0 && strtok(line + 4, "\t ") != NULL) { // Get the effective UID, which is the second value in the line - *uid = (uid_t)atoi(strchr(line + 5, '\t')); - } else if (strncmp(line, "Gid:", 4) == 0) { + *uid = (uid_t)atoi(strtok(NULL, "\t ")); + } else if (strncmp(line, "Gid:", 4) == 0 && strtok(line + 4, "\t ") != NULL) { // Get the effective GID, which is the second value in the line - *gid = (gid_t)atoi(strchr(line + 5, '\t')); + *gid = (gid_t)atoi(strtok(NULL, "\t ")); } else if (strncmp(line, "NStgid:", 7) == 0) { // PID namespaces can be nested; the last one is the innermost one - *nspid = atoi(strrchr(line, '\t')); + char* s; + for (s = strtok(line + 7, "\t "); s != NULL; s = strtok(NULL, "\t ")) { + *nspid = atoi(s); + } nspid_found = 1; } } diff --git a/src/windows/jattach.c b/src/windows/jattach.c index b43e2f8..1318a94 100644 --- a/src/windows/jattach.c +++ b/src/windows/jattach.c @@ -16,7 +16,8 @@ #include #include -#include +#include +#include typedef HMODULE (WINAPI *GetModuleHandle_t)(LPCTSTR lpModuleName); typedef FARPROC (WINAPI *GetProcAddress_t)(HMODULE hModule, LPCSTR lpProcName); @@ -223,32 +224,27 @@ static int read_response(HANDLE hPipe) { return result; } -int main(int argc, char** argv) { - if (argc < 3) { - printf("jattach " JATTACH_VERSION " built on " __DATE__ "\n" - "Copyright 2021 Andrei Pangin\n" - "\n" - "Usage: jattach [args ...]\n" - "\n" - "Commands:\n" - " load threaddump dumpheap setflag properties\n" - " jcmd inspectheap datadump printflag agentProperties\n" - ); - return 1; - } - - int pid = atoi(argv[1]); +int jattach(int pid, int argc, char** argv) { + // When attaching as an Administrator, make sure the target process can connect to our pipe, + // i.e. allow read-write access to everyone. For the complete format description, see + // https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format + SECURITY_ATTRIBUTES sec = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE}; + ConvertStringSecurityDescriptorToSecurityDescriptor("D:(A;;GRGW;;;WD)", SDDL_REVISION_1, + &sec.lpSecurityDescriptor, NULL); char pipeName[MAX_PATH]; sprintf(pipeName, "\\\\.\\pipe\\javatool%d", GetTickCount()); HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - 1, 4096, 8192, NMPWAIT_USE_DEFAULT_WAIT, NULL); + 1, 4096, 8192, NMPWAIT_USE_DEFAULT_WAIT, &sec); if (hPipe == NULL) { print_error("Could not create pipe", GetLastError()); + LocalFree(sec.lpSecurityDescriptor); return 1; } - if (!inject_thread(pid, pipeName, argc - 2, argv + 2)) { + LocalFree(sec.lpSecurityDescriptor); + + if (!inject_thread(pid, pipeName, argc, argv)) { CloseHandle(hPipe); return 1; } @@ -262,3 +258,30 @@ int main(int argc, char** argv) { return result; } + +#ifdef JATTACH_VERSION + +int main(int argc, char** argv) { + if (argc < 3) { + printf("jattach " JATTACH_VERSION " built on " __DATE__ "\n" + "Copyright 2021 Andrei Pangin\n" + "\n" + "Usage: jattach [args ...]\n" + "\n" + "Commands:\n" + " load threaddump dumpheap setflag properties\n" + " jcmd inspectheap datadump printflag agentProperties\n" + ); + return 1; + } + + int pid = atoi(argv[1]); + if (pid <= 0) { + fprintf(stderr, "%s is not a valid process ID\n", argv[1]); + return 1; + } + + return jattach(pid, argc - 2, argv + 2); +} + +#endif // JATTACH_VERSION -- 2.39.5