On 19/04/2021 15:10, Peter Levart wrote:
:
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...


One initial comment is that the attach mechanism is also used for the troubleshooting tools (jcmd, jstack, jmap, ...). This is how tools start the JMX agent in the target VM, or request a stack trace or heap dump, to name a few. It's just the loading of JVMTI agents that would need to be restricted (Java agents use the JPLIS JVMTI agent).

A second comment is that the attach mechanism on Linux and macOS is based on Unix domain sockets and the effective uid/gid of the peer is available. So if you are exploring here then you should be able to just use that rather than changing the handshake. The Windows implementation injects a stub into the target VM to queue the command so there isn't the equivalent.

-Alan


Reply via email to