On Wed, 30 Oct 2024 17:20:49 GMT, Larry Cable <d...@openjdk.org> wrote:

>> 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.
>> 
>> I...
>
> Larry Cable has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   JDK-8342449: fixed missing param in throws msg and renamed local var

src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java line 268:

> 266:          * however we can also check the target pid's signal masks to 
> see if it catches SIGQUIT and only do so if in
> 267:          * fact it does ... this reduces the risk of killing an innocent 
> process in the current ns as opposed to
> 268:          * attaching to the actual target JVM ... c.f: 
> checkCatchesAndSendQuitTo() below.

This still looks pretty risky and dangerous. I'm thinking if it'd make sense to 
check that the target process is a VM process. At least, we know how VM 
processes can use the signal mask. Another concern is that the target VM 
process might be not exactly the same VM the client was expecting to attach. I 
don't know what can be done to ensure this correctness.

src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java line 327:

> 325:     private static final String SIGNAL_MASK_PATTERN = "(?<" + FIELD + 
> ">Sig\\p{Alpha}{3}):\\s+(?<" + MASK + ">\\p{XDigit}{16}).*";
> 326: 
> 327:     private static final long SIGQUIT = 1L << 2;

Q: why not just 3L ? :)

src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java line 340:

> 338:         var readBlk = false;
> 339:         var readIgn = false;
> 340:         var readCgt = false;

Nit:
 - Minor suggestion to order the lines 338-430 same as lines 330-332 and place 
them after them
 - Never liked single-letter identifiers because they are not well searchable. 
I'd suggest to:
   rename `p` to  something like `pattern` or `ptrn` and `m` to something like 
`matcher` or `match`.

src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java line 364:

> 362:                 case "SigIgn": { quitIgn = sigquit; readCgt = true; 
> break; }
> 363:                 case "SigCgt": { quitCgt = sigquit; readIgn = true; 
> break; }
> 364:             }

Q: The `readIgn` and `readCgt` are swapped at lines 362-363. Is it intentional 
or just a typo?

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

PR Review Comment: https://git.openjdk.org/jdk/pull/21688#discussion_r1832048612
PR Review Comment: https://git.openjdk.org/jdk/pull/21688#discussion_r1832037498
PR Review Comment: https://git.openjdk.org/jdk/pull/21688#discussion_r1832040824
PR Review Comment: https://git.openjdk.org/jdk/pull/21688#discussion_r1832042138

Reply via email to