Skip to content

TightDecoder: bound rectangle area to prevent OOM from a malicious server - #2132

Open
acts-1631 wants to merge 1 commit into
TigerVNC:masterfrom
acts-1631:fix-tightdecoder-height-oom
Open

TightDecoder: bound rectangle area to prevent OOM from a malicious server#2132
acts-1631 wants to merge 1 commit into
TigerVNC:masterfrom
acts-1631:fix-tightdecoder-height-oom

Conversation

@acts-1631

Copy link
Copy Markdown

readRect() only caps the rectangle width (TIGHT_MAX_WIDTH), not its
height, which arrives on the wire as an unbounded uint16. A malicious
server can advertise a large framebuffer in ServerInit and then send
a single Tight rectangle up to 2048x65535, causing decodeRect() to
allocate a ~537MB zlib output buffer and, when the pixel format needs
translation, another ~537MB translation buffer for the same
rectangle.

A flat height cap equal to TIGHT_MAX_WIDTH would reject rectangles
that a compliant server can legitimately send: EncodeManager only
splits a changed rectangle once its area exceeds SubRectMaxArea
(65536), so a narrow, tall rectangle (a thin scrollbar or resize
handle on a display or monitor stack taller than 2048px) can be sent
unsplit with a height well above 2048.

This enforces the same area bound the encoder already honours
instead of an arbitrary height limit, keeping the worst-case
allocation to TIGHT_MAX_AREA * bpp (~256KB) while still accepting
every rectangle a compliant encoder can produce.

…rver

readRect() only capped the rectangle width (TIGHT_MAX_WIDTH), not its
height, which arrives on the wire as an unbounded uint16. A malicious
server can advertise a large framebuffer in ServerInit and then send a
single Tight rectangle up to 2048x65535, causing decodeRect() to
allocate a ~537MB zlib output buffer and, when the pixel format needs
translation, another ~537MB translation buffer for the same rectangle.

A simple height cap equal to TIGHT_MAX_WIDTH would reject rectangles
that a compliant server can legitimately send: EncodeManager only
splits a changed rectangle once its area exceeds SubRectMaxArea
(65536), so a narrow, tall rectangle (e.g. a thin scrollbar or resize
handle on a display or monitor stack taller than 2048px) can be sent
unsplit with a height well above 2048.

Enforce the same area bound the encoder already honours instead of an
arbitrary height limit. This keeps the worst-case allocation to
TIGHT_MAX_AREA * bpp (~256KB) while accepting every rectangle a
compliant encoder can produce.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant