atl-dyon opened a new issue, #927: URL: https://github.com/apache/mina-sshd/issues/927
### Version 2.14.0 ### Bug description SSHD 2.14.0 and later can run kex.init on the thread that writes data, while an I/O thread handles the next key exchange packet. The I/O thread then uses a key exchange that is not ready. The session fails with "ECDH not initialised" or a NullPointerException. The client sees "early EOF" We first observed this in sshd 2.16.0 in Bitbucket DC 10.2. ## Reproducer `RekeyRace.java` is attached. It uses the public API only. ``` mvn -q compile exec:java -Dexec.args="65536 33554432 20 8 0 0" mvn -q compile exec:java -Dexec.args="65536 33554432 20 8 0 0" -Dsshd.version=2.13.2 ``` - 2.16.0: failed in 5 of 5 runs. - 2.13.2: passed 4 of 4 runs. The server writes from its own thread, and both sides use the same re-key limit. I also ran `git clone` against a server on 2.16.0 with OpenSSH 10.3 as the client. With a 64K re-key limit on both sides, all rounds failed. ## Cause I think this comes from 9e4e040e, "Clean-up: timeout-free KEX". It replaced `initFuture.await()` with `initFuture.addListener()` in `doKexNegotiation`. The listener can run `performKexNegotiation`, and so `kex.init`, on the thread that completes the future. That can be the thread that writes channel data. An I/O thread can reach `kex.next` while this runs. I tried a subclass of `ServerSessionImpl` that waits on `kexState` before `handleKexMessage`. This allowed me to pass testing and not observe the bug. Note that the `ReKeyRace.java` is AI generated but accurately showcases the issue. [RekeyRace.java](https://github.com/user-attachments/files/33366384/RekeyRace.java) ### Actual behavior An `nio2` thread throws from `AbstractSession.handleKexMessage`: ``` java.lang.NullPointerException: Cannot invoke "KeyExchange.next(int, Buffer)" because "this.kex" is null java.lang.IllegalStateException: ECDH not initialised. java.lang.IllegalStateException: Not initialized ``` ``` at org.apache.sshd.server.kex.DHGServer.next(DHGServer.java:109) at org.apache.sshd.common.session.helpers.AbstractSession.handleKexMessage(AbstractSession.java:771) at org.apache.sshd.common.session.helpers.AbstractSession.messageReceived(AbstractSession.java:515) at org.apache.sshd.common.io.nio2.Nio2Session.handleReadCycleCompletion(Nio2Session.java:409) ``` ### Expected behavior Rekey should occur without error, and the session transfer continues to completion. ### Relevant log output ```Shell ``` ### Other information _No response_ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
