Skip to content

Instantly share code, notes, and snippets.

@SubOptimal
Last active March 19, 2019 06:25
Show Gist options
  • Save SubOptimal/516d8dfba07fd12ecc19 to your computer and use it in GitHub Desktop.
Save SubOptimal/516d8dfba07fd12ecc19 to your computer and use it in GitHub Desktop.
Java attach API - attach to JVM of different user

The problem to attach to a JVM running with other user credentials is, that the Unix domain socket must be effectively owned by the user which process wants to attach to the target. As the socket must be created by the target JVM there is no way without using root privileges in between to change the permission.

example 1

user1 java -cp $JAVA_HOME/lib/tools.jar:. AttachTarget
user2 java -cp $JAVA_HOME/lib/tools.jar:. AttachClient pid_of_user1_jvm

will fail with java.io.IOException: Operation not permitted

example 2

user1 java -cp $JAVA_HOME/lib/tools.jar:. -XX:+StartAttachListener AttachTarget
user2 java -cp $JAVA_HOME/lib/tools.jar:. AttachClient pid_of_user1_jvm

will fail with java.io.IOException: well-known file is not secure (see LinuxVirtualMachine.c)

example 3

user1 java -cp $JAVA_HOME/lib/tools.jar:. -XX:+StartAttachListener AttachTarget
root chown user2.user2 /tmp/.java_pid${pid_of_user1_jvm}
user2 java -cp $JAVA_HOME/lib/tools.jar:. AttachClient pid_of_user1_jvm

will attach to the user1 JVM vm = sun.tools.attach.LinuxAttachProvider@62766e80: ...

example 4

user1 java -cp $JAVA_HOME/lib/tools.jar:. AttachTarget
root touch /proc/${pid_of_user1_jvm}/cwd/.attach_pid${pid_of_user1_jvm}
root kill -s 3 pid_of_user1_jvm
root chown user2.user2 /tmp/.java_pid${pid_of_user1_jvm}
user2 java -cp $JAVA_HOME/lib/tools.jar:. AttachClient pid_of_user1_jvm

will attach to the user1 JVM vm = sun.tools.attach.LinuxAttachProvider@62766e80: ...

import com.sun.tools.attach.VirtualMachine;
public class AttachClient {
public static void main(String[] args) throws Exception {
String pid = args[0];
VirtualMachine vm = VirtualMachine.attach(pid);
System.out.println("vm = " + vm);
vm.detach();
}
}
import java.lang.management.ManagementFactory;
import java.io.File;
public class AttachTarget {
public static void main(String[] args) throws Exception {
String jvm = ManagementFactory.getRuntimeMXBean().getName();
String pid = jvm.substring(0, jvm.indexOf('@'));
System.out.println("pid: " + pid);
File pidFile = new File("/tmp/.java_pid" + pid);
System.out.println("exists: " + pidFile.exists());
Thread.sleep(600_000);
}
}
@greenrd
Copy link

greenrd commented Apr 1, 2016

Which JDK is this? With the Oracle JDK (8, but also older versions, I think), there is no /tmp/.java_pid$PID file - there is a /tmp/hsperfdata_$USERNAME/$PID file though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment