RFR: 8200559: Java agents doing instrumentation need a means to define auxiliary classes [v2]

Peter Levart plevart at openjdk.java.net
Mon Apr 19 14:10:34 UTC 2021


On Mon, 19 Apr 2021 09:34:56 GMT, Alan Bateman <alanb at openjdk.org> wrote:

> an application or library can use the attach mechanism (directly or via the attach API in a child VM) to load an agent and leak the Instrumentation object. This is the genie that somehow needs to be put back in its bottle. One approach that I mentioned here to create is a less powerful Instrumentation object for untrusted agents. Trusted agents would continue to the full-power

I hear Rafael that dynamic attach is important to support monitoring and instrumenting large numbers of JVMs with no preparations (i.e. without issueing special command-line options to enable it). As I understand, current attach mechanism is designed to allow a process running under the same UID as the JVM or under root to attach to the JVM.

What if this dynamic attach mechanism was modified so that only a process running under root could dynamically attach to the JVM? Old behavior would be enabled by special command line option, so by default, dynamic attach would be limited to tools running under root. Rafael mentions discovery, monitoring and instrumenting large number of JVMs running on hosts, so if one such tool has to attach to different JVMs running under different UIDs, it has to run as root now anyway.

With such default "secure" dynamic attach and when the JVM is not running as root (which is a recommended security practice anyway), a library in such JVM could not attach back to the same JVM even through spawning sub-processes.

How to achieve such "secure" dynamic attach? One way that comes to mind is a modified handshake. Currently, I think at least on Linux, the tool that wishes to attach to the JVM searches for a special UNIX socket (`$PWD/.java_pid<vmid>`, `/tmp/.java_pid<vmid>`) and if not found, creates a special attach file (`$PWD/.attach_pid<vmid>`, `/tmp/.attach_pid<vmid>`) to signal the JVM to create a listening UNIX socket under mentioned special path, then it connects to the socket. The UNIX socket file has UID:GID set to effective UID:GID of the JVM process and permissions to 0600, so only a tool running under same UID or root can connect to such socket.

In modified handshake, JVM not running as root could not create a UNIX socket file with permissions to allow only root user to connect to it, but a tool running under root could create a listening UNIX socket with permission to allow JVM to connect to it in a way that the JVM connecting to such socket would know that the listening process is running as root. Simply by checking the owner of the listening UNIX socket file. Such socket file would have to have permission 0666 in order to allow JVMs running under any UID to connect to it, but otherwise be "hidden". This can be achieved by the tool creating a special directory and a UNIX socket in this directory, say: `/tmp/.attach_dir<tool pid>/<random string>`, The directory UID:GID would be 0:0 and have permission 0711. This means, any user could connect to the socket as long as it knows the `<random string>`, but no user but root can list the content of the directory to discover the name of the socket file. The last piece of the puzzle
  is how to signal to the JVM about the name of the socket file. Well, creating a file with the content holding the name of the socket file would be OK, as long as only target JVM could read it. File permissions could be set such that any process running under the same UID as the JVM could read the file. This would give a rouge library a chance to connect to the tool and pretend to be the monitoring JVM, but it could not connect to back to the JVM though...

WDYT?

-------------

PR: https://git.openjdk.java.net/jdk/pull/3546


More information about the serviceability-dev mailing list