RFR: 8342449: reimplement: JDK-8327114 Attach in Linux may have wrong behavior when pid == ns_pid
Larry Cable
duke at openjdk.org
Fri Oct 25 18:19:33 UTC 2024
the implementation I originally provided does not in fact solve the issue!
the attach protocol initiation "handshake" requires that the "attacher" (the caller of this code) and the "attachee"(the target JVM to be "attached" to) *must* share a "/tmp" (or access to the attachee's `cwd`) in common in order to rendezvous on the "attach" socket (created in the /tmp or attachee `cwd` filesystem).
"attacher" and "attachee" JVM processes are guaranteed to share a common directory/filesystem when thy occupy the same "mount namespace", this is the environment in which "peers" exist, and the attach
handshake (initiated by the attacher) can use "/tmp" to establish the socket connection with the attachee.
with the advent of "containers" (implemented in Linux via various namespaces, e.g.: pid & mount) another "attacher" and "attachee" relationship exists, that of "attacher" (namespace ancestor) and "attachee" (namespace descendant).
in this environment it is possible (and highly probable) that the "attacher" and the "attachee" do not share a directory in common.
In this scenario the "attacher" must resort to handshaking with the attachee via the /proc filesystem in order to access the "attachee's" directory from the "attacher".
In order to achieve this rendezvous, the "attachee" must occupy a descendant, or same, (pid) namespace of, or as, the "attacher".
since (pid) namespaces are hierarchical, a descendant process (in its own descendent pid namespace) will also occupy all its ancestor (pid) namespaces (between it and the 'root' or 'host' pid namespace) with a unique pid in each of those "interstitial" (pid) namespace(s).
thus the "attachee" directory is accessible, via an "ancestor's" (or peer's) /proc filesystem using the pid of the "attachee" that is associated with it in that (pid) namespace.
thus an "ancestor" "attacher" can handshake with a descendant "attachee" in this fashion.
therefore an "attacher" has two choices when attempting to attach:
- use the /proc/<pid>/root/tmp path to the "attachee's" /tmp (or its cwd)
- this works with both peers and descendants
- use /tmp
- this only works if the "attacher" and "attachee" share a /tmp in common
the obvious choice is to default to /proc/<pid>/root/tmp (or cwd) however there is an issue with this; should the attachee have elevated privileges, the attacher may not have r/w permission on the attachee's /proc/<pid>/root (or cwd) path.
In these circumstances, the "attacher" can only resort to /tmp which may or may not be in common with the "attachee".
the logic required for an "attacher" to determine if an "attachee" /tmp *is* in common unfortunately requires read access (from the attacher) to the"attachee's" /proc filesystem (namely to read namespace identities and to also 'stat(2)' the /proc/<pid>/root/tmp directory to obtain device and inode values for comparison in order to determine if "/tmp" is in common.
when the "attachee" has elevated privileges, this access is not available to the "attacher".
therefore in such circumstances, the "attacher" has no choice but to attempt
to use /tmp and simply timeout the handshake if in fact the "attachee" does not share a /tmp in common
In this elevated case, there is a remote possibility that another process (in the attacher's pid ns) shares the same pid as the attachee (in its descendant pid ns) in this case, if they do not share a filesystem in common the attacher may attempt
to attach to an unsuspecting process in its pid ns, this could result in that process being killed.
In order to reduce the possibility of this mis-attach resulting in process death, the attacher now tests the attachee to determine if it can participate in the attach handshake, by inspecting its signal masks and not delivering the signal to
the attachee if it is not catching the signal.
-------------
Commit messages:
- JDK-8342449: fixed a couple of jcheck issues, modified AttachNotSupportedException to indicate that attachee is not ready to accept SIGQUIT
- JDK-8342449: resolve remaing jcheck issues, amend AttachNotSupportedException when attachee is not ready to accept SIGQUIT
- JDK-8342449: cleaned up tabs etc for jcheck
- JDK-8342449: ignore blocked SIGQUIT in checkCatchesAndSendQuitTo
- JDK-8342449: suppressed AttachNotSupportedException from checkCatchesAndSendQuitTo
- JDK-8342449: reimplement: JDK-8327114 Attach in Linux may have wrong behavior when pid == ns_pid
Changes: https://git.openjdk.org/jdk/pull/21688/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=21688&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8342449
Stats: 158 lines in 1 file changed: 71 ins; 63 del; 24 mod
Patch: https://git.openjdk.org/jdk/pull/21688.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/21688/head:pull/21688
PR: https://git.openjdk.org/jdk/pull/21688
More information about the serviceability-dev
mailing list