]> git.sven.stormbind.net Git - sven/jattach.git/commitdiff
New upstream version 2.1 upstream/2.1
authorSven Hoexter <sven@stormbind.net>
Mon, 25 Jul 2022 18:38:38 +0000 (20:38 +0200)
committerSven Hoexter <sven@stormbind.net>
Mon, 25 Jul 2022 18:38:38 +0000 (20:38 +0200)
Makefile
README.md
jattach.spec
src/posix/jattach.c
src/posix/jattach_openj9.c
src/posix/psutil.c
src/windows/jattach.c

index 4b04acfd31455cd610d7a7eb5b7616550aa12be2..7ff43df6cdee496660afb9899950779ba50b7aa7 100644 (file)
--- 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
index 711ffe647bc81b9d5fa14c873cfa8c431cdf2e5a..369945153f6106091cefebc6889bbf52c0e48dbb 100644 (file)
--- 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).
index 529cf0e7b1c18687b083ebbcdab149af7108b21c..452ab91236ac653259428e2f8182ba5186b1ec82 100644 (file)
@@ -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 <incubos@yandex.com> - 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 <incubos@yandex.com> - 2.0-1
 - Attach to OpenJ9 VMs
 - Pass agent error codes
index 804d13daee52beff86aef0e1dae473c8c611620a..53d9dfba127d352752eef713affd7710af7db30e 100644 (file)
@@ -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
index f34f4cc79447eec298f021df132235d4f2a444ba..deab4c68f150f041844e1c25de6aaed4a22b602d 100644 (file)
@@ -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;
 }
 
index 847a0609a332f1eff46eebe5515ee76c873b8347..9beea88f54b095c09db0b33a34985a12d9c4b0d5 100644 (file)
@@ -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;
         }
     }
index b43e2f875e2aeaef9f692c4282859ee7e0ce5652..1318a94541a2ef6706bde4d361cc81c4d28385f3 100644 (file)
@@ -16,7 +16,8 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <Windows.h>
+#include <windows.h>
+#include <sddl.h>
 
 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 <pid> <cmd> [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 <pid> <cmd> [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