diff options
| author | user <user@clank> | 2026-09-22 16:02:45 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-22 16:02:45 +0200 |
| commit | f084772cf3c021fa2315fb17a0697c4be8c59a77 (patch) | |
| tree | 7eca149269dafb78c40964cf185369e206763eb8 /include | |
| parent | sh: background dhcp at boot so the prompt is never blocked (diff) | |
| download | gbos-f084772cf3c021fa2315fb17a0697c4be8c59a77.tar.gz gbos-f084772cf3c021fa2315fb17a0697c4be8c59a77.tar.xz gbos-f084772cf3c021fa2315fb17a0697c4be8c59a77.zip | |
net: three TCP receive bugs - caller corruption, data loss, early EOF
Found by writing nc(1): a 96-byte receive buffer against a host that
answers in 200-byte segments hung the process every time.
- recv/recv_nb copied RXLEN bytes into the caller's buffer and never
looked at the caller's maxlen, so any short buffer got overrun and its
stack smashed. Deliver min(RXLEN, maxlen) and keep the tail in RXBUF
for the next call. wget only survived because its buffer (220) happens
to exceed our MSS.
- tcp_buffer_data overwrote RXBUF from offset 0 on every segment, so a
segment arriving before the app drained the previous one destroyed
unread bytes - silent, undetectable data loss. Append at RXBUF+RXLEN
instead, and drop (without advancing rcv_nxt) when it doesn't fit, so
the peer retransmits once there's room. RXLEN is one byte, so 255 is
the capacity that matters, not RXBUF's 288.
- A draining recv now clears RXLEN as well as HASRX: RXLEN is the append
offset, and a stale one made every later segment look too big to fit,
stalling the connection until the peer gave up.
- A FIN past a gap is not end-of-stream. tcp_in accepted any FIN whose
segment carried no data, without a sequence check, marking the socket
DONE and making recv report EOF at the hole - truncating a transfer
right before its last segments. Decide in-order-ness once, before
rcv_nxt moves, and re-ACK an out-of-order FIN instead.
Verified against a 6300-byte reply received while sending 831 bytes:
byte-exact (6339 = payload + banner, 303 lines, first/mid/last intact),
plus no regression in ping / nslookup / wget / irc.
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions
