Forward terminal window size to guest PTY #75

Merged
rawan merged 5 commits from fix_signals_resize into development 2026-04-01 13:13:40 +00:00
Member

#72

NOTE : This branch contains the changes of both #70 and #73
so either merge this only to development and close the parent PR ( #73 )
or merge this after parent PR gets merged

https://forge.ourworld.tf/geomind_code/my_hypervisor/issues/72 **NOTE** : This branch contains the changes of both #70 and #73 so either merge this only to development and close the parent PR ( https://forge.ourworld.tf/geomind_code/my_hypervisor/pulls/73 ) or merge this after parent PR gets merged
fix: fix broken interactive signal handling
All checks were successful
Unit and Integration Test / test (push) Successful in 2m19s
a00dd8f7fa
feat: forward resize
All checks were successful
Unit and Integration Test / test (push) Successful in 1m49s
eaf140780e
fix: fixed silent errors
All checks were successful
Unit and Integration Test / test (push) Successful in 1m51s
c1cfbadadd
Owner

Sounds working, good job

Sounds working, good job
mahmoud approved these changes 2026-03-30 09:35:09 +00:00
Dismissed
mahmoud dismissed mahmoud's review 2026-03-30 09:42:58 +00:00
Reason:

Approved by mistake

rawdaGastan requested changes 2026-03-31 13:25:23 +00:00
Dismissed
rawdaGastan left a comment
Owner

The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data.

The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will:

Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols)
Resize the terminal to whatever garbage values those next 4 bytes decode to
The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic

The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data. The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will: Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols) Resize the terminal to whatever garbage values those next 4 bytes decode to The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic
@ -6,0 +65,4 @@
self.pos += 1;
if self.pos == RESIZE_MSG_LEN {
let rows = u16::from_be_bytes([self.buf[4], self.buf[5]]);
let cols = u16::from_be_bytes([self.buf[6], self.buf[7]]);
Owner

we should validate rows and cols to not be 0

we should validate rows and cols to not be 0
rawan marked this conversation as resolved
@ -156,0 +250,4 @@
fn test_resize_constants_match_protocol() {
// These bytes must match encode_resize() output in my_hypervisor-lib/src/vsock/protocol.rs
// If this test fails, the two crates have diverged.
assert_eq!(RESIZE_MAGIC, [0x01, 0x52, 0x53, 0x5a]); // SOH + "RSZ"
Owner

this will always pass even we changed the magic in protocol.rs

this will always pass even we changed the magic in protocol.rs
Author
Member

there is a corresponding test in protocol.rs that checks the same thing:

  fn test_encode_resize_known_values() {
        let msg = encode_resize(24, 80);
        assert_eq!(msg, [0x01, 0x52, 0x53, 0x5a, 0x00, 24, 0x00, 80]);
    }

That way if either side changes the format, one of the two tests breaks.

but we can add dev-dependency so that tests can use the same constant

there is a corresponding test in protocol.rs that checks the same thing: ``` fn test_encode_resize_known_values() { let msg = encode_resize(24, 80); assert_eq!(msg, [0x01, 0x52, 0x53, 0x5a, 0x00, 24, 0x00, 80]); } ``` That way if either side changes the format, one of the two tests breaks. but we can add dev-dependency so that tests can use the same constant
rawdaGastan marked this conversation as resolved
Author
Member

@rawdaGastan wrote in #75 (comment):

The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data.

The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will:

Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols) Resize the terminal to whatever garbage values those next 4 bytes decode to The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic

this is very low risk case because:

It's on the stdin direction, not stdout. The user would have to type or pipe the exact bytes 0x01 0x52 0x53 0x5a into their terminal input. Running cat /bin/some_binary produces output on stdout (guest → host), which is not parsed for resize markers

The only way binary data hits this path is if someone does something like echo -e '\x01RSZ...' | chvm attach vm1 or cat binary_file | chvm attach vm1 which is an unusual edge case

so here are some suggestions if we do need to fix it:

  • Use a separate vsock port or channel for control messages
  • Add a checksum byte after the payload, ex: [magic 4B] [rows 2B] [cols 2B] [checksum of rows+cols 1B]

what do you think?

@rawdaGastan wrote in https://forge.ourworld.tf/geomind_code/my_hypervisor/pulls/75#issuecomment-16796: > The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data. > > The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will: > > Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols) Resize the terminal to whatever garbage values those next 4 bytes decode to The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic this is very low risk case because: It's on the stdin direction, not stdout. The user would have to type or pipe the exact bytes 0x01 0x52 0x53 0x5a into their terminal input. Running cat /bin/some_binary produces output on stdout (guest → host), which is not parsed for resize markers The only way binary data hits this path is if someone does something like `echo -e '\x01RSZ...' | chvm attach vm1` or `cat binary_file | chvm attach vm1` which is an unusual edge case so here are some suggestions if we do need to fix it: - Use a separate vsock port or channel for control messages - Add a checksum byte after the payload, ex: [magic 4B] [rows 2B] [cols 2B] [checksum of rows+cols 1B] what do you think?
fix: added 0 rows, cols check
All checks were successful
Unit and Integration Test / test (push) Successful in 1m55s
a193e7b888
Owner

@rawan wrote in #75 (comment):

@rawdaGastan wrote in #75 (comment):

The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data.
The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will:
Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols) Resize the terminal to whatever garbage values those next 4 bytes decode to The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic

this is very low risk case because:

It's on the stdin direction, not stdout. The user would have to type or pipe the exact bytes 0x01 0x52 0x53 0x5a into their terminal input. Running cat /bin/some_binary produces output on stdout (guest → host), which is not parsed for resize markers

The only way binary data hits this path is if someone does something like echo -e '\x01RSZ...' | chvm attach vm1 or cat binary_file | chvm attach vm1 which is an unusual edge case

so here are some suggestions if we do need to fix it:

  • Use a separate vsock port or channel for control messages
  • Add a checksum byte after the payload, ex: [magic 4B] [rows 2B] [cols 2B] [checksum of rows+cols 1B]

what do you think?

we can document it

@rawan wrote in https://forge.ourworld.tf/geomind_code/my_hypervisor/pulls/75#issuecomment-16966: > @rawdaGastan wrote in #75 (comment): > > > The resize protocol works by sending a special 4-byte marker \x01RSZ followed by 4 bytes of size data through the same stream as normal terminal data. > > The problem: if a user does something like cat /bin/some_binary or pipes binary data, and that binary data happens to contain the bytes 0x01, 0x52, 0x53, 0x5a somewhere, the guest parser will think it's a resize message. It will: > > Swallow 8 bytes of real data (the 4 "magic" bytes + the next 4 bytes it thinks are rows/cols) Resize the terminal to whatever garbage values those next 4 bytes decode to The user sees corrupted output and their terminal may resize to something unusable. With only 4 bytes of magic > > this is very low risk case because: > > It's on the stdin direction, not stdout. The user would have to type or pipe the exact bytes 0x01 0x52 0x53 0x5a into their terminal input. Running cat /bin/some_binary produces output on stdout (guest → host), which is not parsed for resize markers > > The only way binary data hits this path is if someone does something like `echo -e '\x01RSZ...' | chvm attach vm1` or `cat binary_file | chvm attach vm1` which is an unusual edge case > > so here are some suggestions if we do need to fix it: > > * Use a separate vsock port or channel for control messages > * Add a checksum byte after the payload, ex: [magic 4B] [rows 2B] [cols 2B] [checksum of rows+cols 1B] > > what do you think? we can document it
doc: document resize protocol edge case
All checks were successful
Unit and Integration Test / test (push) Successful in 2m21s
29b03e7564
Merge branch 'development' into fix_signals_resize
All checks were successful
Unit and Integration Test / test (push) Successful in 1m53s
58922d5e76
rawan merged commit 377d00690d into development 2026-04-01 13:13:40 +00:00
rawan deleted branch fix_signals_resize 2026-04-01 13:13:40 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
geomind_code/my_hypervisor!75
No description provided.