mojira.dev
MC-308621

Race condition in the dedicated server's compression setup

The dedicated server enables login compression from the compression packet write future listener. Netty does not guarantee that this listener will run before later packets are queued for write. As a result, packets sent immediately after the compression packet, such as the login success packet, can be queued before compression handlers are installed, while the client already expects subsequent packets to be compressed.

This is difficult to reproduce with the default nio/epoll transport because writes often complete immediately, but it can happen if the write completion is delayed, for example due to a full socket buffer. It becomes consistently reproducible with asynchronous transports such as io_uring (as there is a submission / completion queue).

Affected code in ServerLoginPacketListenerImpl.java:

if (this.server.getCompressionThreshold() >= 0 && !this.connection.isMemoryConnection()) {
                this.connection.send(new ClientboundLoginCompressionPacket(this.server.getCompressionThreshold()), PacketSendListener.thenRun(() -> {
                    this.connection.setupCompression(this.server.getCompressionThreshold(), true);
                }));
            }

A potential fix is to instead of using the Netty future it schedules an EventLoop task right after the compression packet to setup the compression. This will ensure the compression is set up right after writing the compression packet.

Related Paper pr with fix: Fix login compression setup ordering/race condition by Beaness · Pull Request #13929 · PaperMC/Paper

Comments 0

No comments.

Beanes

Nathan Wolf

Plausible

Platform HC

Normal

Networking

26.1.2

26.4 Snapshot 5

Retrieved