On Mon, 19 Apr 2021 09:34:56 GMT, Alan Bateman <al...@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

Reply via email to