Disallowing the dynamic loading of agents by default

Eirik Bjørsnøs eirbjo at gmail.com
Mon Apr 3 19:33:12 UTC 2017


I can share three examples of agents I've developed the past few
years where this change is or could have been disruptive to some extent:


JettyConsole takes war files and make them "executable" with java -jar by
embedding the Jetty servlet container inside the war file. HTTP/2 support
is implemented as an agent which uses dynamic agent loading to replace TLS
implementation classes in the JDK at bootstrap to allow Jetty's HTTP/2
implementation to offer ALPN (required for H2).

Changing this plugin to use a command line invoked agent would defeat the
whole purpose of JettyConsole, which is to distribute a whole Java Servet
webapp in a single binary artifact. The workaround would be to fork the JVM
at startup. (Less relevant in the future since my understanding is that
ALPN will be supported in JDK9..)


NotSoSerial is a Java Agent designed as a mitigation effort against Java
deserialization attacks.

NotSoSerial used dynamic agents, however mostly to ease unit testing. I was
however in discussion with a pretty large platform vendor who were
considering the option of deploying a hotfix to their customer using
NotSoSerial's dynamic agent support. In the end, I think they ended up
using just the command line agent. But from a security perspective, having
the option of rolling out an emergency fix dynamically has some desired


Skybar (presented at JVMLS15) is a code coverage instrumentation agent,
built with a focus on performance. Skybar makes it is possible to record
two "runs" of code and compare these runs afterwords. This can be
very useful in troubleshooting weird production issues which can be
extremely hard, expensive or even impossible to reproduce in a lab. In this
mode, it's very useful to attach the agent dynamically, since you might not
know that you need it until your system has been running for a while.

Outside Skybar, I've been using dynamic agents multiple times in the past
to instrument code (JDK or user) to troubleshoot shy issues in production.
It's made a superhero for a day for several clients :-)


On Thu, Mar 30, 2017 at 5:38 PM, <mark.reinhold at oracle.com> wrote:

> // Moving the general discussion to jigsaw-dev for the record;
> // bcc'ing {hotspot-runtime,serviceability}-dev for reference.
> Andrew,
> Thanks for your feedback on this topic [1][2][3].
> First, we apologize for the way in which this topic was raised.  Our
> intent was to post a proposal for discussion prior to code review, but
> unfortunately that review was posted prematurely (as is evident by its
> inclusion of Oracle-internal e-mail addresses and URLs).
> Second, I agree with your earlier analysis as to the security impact of
> this change.  If an attack is possible via this vector then closing the
> vector would only slow the attack, not prevent it.
> The motivation for this change is, however, not merely to improve the
> security of the platform but to improve its integrity, which is one of
> the principal goals of the entire modularity effort.  Integrity has
> benefits for security and also for maintainability, of both the JDK
> itself and of code that runs upon it, since it makes it clear exactly
> which APIs are intended for external use, and which are not.
> To improve platform integrity we've strongly encapsulated (most) of the
> internal APIs of the JDK.  That can be, as we all know, a source of pain
> for developers trying to get existing applications to run on JDK 9, so
> we've provided workarounds via the encapsulation-busting `--add-opens`
> and `--add-exports` command-line options and, recently, the temporary
> but more powerful (and verbose) `--permit-illegal-access` option.
> There are no API equivalents to these command-line options [4].  That's
> intentional: We want developers and deployers using Java out-of-the-box
> to be assured that their code is only using APIs actually intended for
> external use.  They can choose explicitly to expose internal APIs, via
> the command line, but then that's a deliberate choice that they make, and
> they own the consequences.  It's reasonable to allow this via the command
> line since we assume that anyone with access to the command line already
> has the power to corrupt the JDK in any way they please.
> The proposal to disable the loading of dynamic agents by default is one
> more part of the overall integrity story.  As things stand today, code in
> any JAR file can use the `VirtualMachine.loadAgent` API to load an agent
> into the JVM in which it's running and, via that agent, break into any
> module it likes.  Changing the default and providing a new command-line
> option, in this case `-XX:+EnableDyanmicAgentLoading`, is consistent with
> the other encapsulation-busting options we've introduced.  It allows a
> developer or deployer to choose to bend, if not violate, the integrity
> of the platform, yet also to know that by default the platform is whole.
> (Changing this default is also consistent, as Alan has noted, with the
> original intent of the `VirtualMachine.loadAgent` API.)
> I understand your points about the practical difficulties of having to
> educate users about this new option and enhance startup scripts to use
> the option only when invoking JDK 9.  Isn't it already the case, however,
> that migrating existing applications to JDK 9 is often going to require
> the use of a few new options anyway, in order to expose internal APIs?
> If so then would it really be that much more burdensome for users also
> to think explicitly, at the same time, about whether they want to enable
> dynamic agent loading?
> This change would be disruptive to some but it's the best way we've
> found, so far, to preserve platform integrity in the face of dynamic
> agent loading.  If there's a better way to do that, we'd like to know.
> - Mark
> [1] http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/
> 2017-March/022948.html
> [2] http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/
> 2017-March/022951.html
> [3] https://bugs.openjdk.java.net/browse/JDK-8177154
> [4] There are limited reflective APIs via which code in a module can
>     apply some of these operations to just that module, and via which
>     code that creates a module layer can do so for modules in that
>     layer, but none of these APIs can break into arbitrary modules.

More information about the jigsaw-dev mailing list