On Wed, 3 Jul 2024 13:58:51 GMT, Kevin Walls <kev...@openjdk.org> wrote:
> CmdLine::is_executable() looks wrong, surely an empty line is not executable. > > With this change, in DCmd::parse_and_execute() we will avoid needlessly > entering the code block to try and execute the command. > > DCmd tests all good: > make images test TEST="test/hotspot/jtreg/serviceability/dcmd > test/jdk/sun/tools/jcmd" At the point where this is checked, the commandline string is still not parsed. I do not want any `assert`s regarding the structure of untrusted input. Anyway, PoC of getting "empty" lines such that `is_empty()` is true. I read the code: ```c++ // diagnosticFramework.cpp:387 DCmdIter iter(cmdline, '\n'); // <--- Delimiter right there Hypothesis: Multiple newlines in a message will lead to empty lines. First attempt: I used `jcmd` directly, this failed, as `jcmd` does some clean up on its own. So I had to go with connecting to the PID using Python. My Python 'attacker': import socket import os # My Java PID, connect with JCMD ordinarily to your Java process first to create the PID file, then # replace the numbers with your Java PID socket_path = "/proc/2603121/root/tmp/.java_pid2603121" client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) print("Connect") print(client.connect(socket_path)) # // The request is: # // <ver>0<cmd>0<arg>0<arg>0<arg>0 # // where <ver> is the protocol version (1), <cmd> is the command # // name ("load", "datadump", ...), and <arg> is an argument connect_payload = "1\x00jcmd\x00\n\n\n\x00\n\n\n\x00\n\n\n\x00" print("Sending payload") print(client.sendall(connect_payload.encode())) print("Sent") # Receive a response from the server response = client.recv(4096) print(f'Received response: {response.decode()}') Later on, in a gdb session for my Java program and where I've connected to the Java process using my Python program: (gdb) p line.is_empty() $6 = true (gdb) p cmdline $7 = 0x7fff68240fc9 "\n\n\n" (gdb) p line $8 = {<StackObj> = {<No data fields>}, _cmd = 0x7fff68240fc9 "\n\n\n", _cmd_len = 0, _args = 0x7fff68240fc9 "\n\n\n", _args_len = 0} (gdb) p bt No symbol "bt" in current context. (gdb) bt #0 DCmd::parse_and_execute (source=DCmd_Source_AttachAPI, out=0x7fffaa62ecc0, cmdline=0x7fff68240fc9 "\n\n\n", delim=32 ' ', __the_thread__=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/share/services/diagnosticFramework.cpp:399 #1 0x00007ffff58f8748 in jcmd (op=0x7fff68240fb0, out=0x7fffaa62ecc0) at /home/johan/jdk/open/src/hotspot/share/services/attachListener.cpp:209 #2 0x00007ffff58f91ae in AttachListenerThread::thread_entry (thread=0x7fff8c001010, __the_thread__=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/share/services/attachListener.cpp:418 #3 0x00007ffff6036294 in JavaThread::thread_main_inner (this=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/share/runtime/javaThread.cpp:757 #4 0x00007ffff6036129 in JavaThread::run (this=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/share/runtime/javaThread.cpp:742 #5 0x00007ffff67c5fb7 in Thread::call_run (this=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/share/runtime/thread.cpp:225 #6 0x00007ffff6549e28 in thread_native_entry (thread=0x7fff8c001010) at /home/johan/jdk/open/src/hotspot/os/linux/os_linux.cpp:858 #7 0x00007ffff7c94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442 #8 0x00007ffff7d26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 (gdb) Oh, and also, the output of my Python running: Connect None Sending payload None Sent Received response: -1 java.lang.IllegalArgumentException: Unknown diagnostic command ------------- PR Comment: https://git.openjdk.org/jdk/pull/20006#issuecomment-2254454215 PR Comment: https://git.openjdk.org/jdk/pull/20006#issuecomment-2254454540