⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content

Conversation

@kitknox
Copy link

@kitknox kitknox commented Jan 12, 2026

The size check in TsnetGetIps, TsnetErrmsg, and TsnetGetRemoteAddr used an incorrect condition (len(out) < len(s)-1) that failed to account for the NUL terminator. When buflen equaled or was one less than the string length, the code would write past the buffer bounds.

The size check in TsnetGetIps, TsnetErrmsg, and TsnetGetRemoteAddr used an
incorrect condition (len(out) < len(s)-1) that failed to account for the NUL
terminator.  When buflen equaled or was one less than the string length, the
code would write past the buffer bounds, causing a panic that terminates the
host process.
@bradfitz bradfitz requested a review from raggi January 12, 2026 22:39
Copy link
Member

@bradfitz bradfitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we could factor this out into a helper func, too.

Letting @raggi review, as I think he was the most recent owner of this code.

@raggi
Copy link
Member

raggi commented Jan 13, 2026

@kitknox I do prefer the length checks written as they are here, but I am not following the commit description. The commit description seems to claim that this patch fixes an out of bounds write, but copy() in Go only copies up to max(len(dest), len(src)) items, and the final write inside the conditional blocks is bound by out[len(out)-1], so I don't see an out of bounds write unless the caller passed a buflen larger than buf. Can you confirm / provide a reproduction of the issue you saw?

@kitknox
Copy link
Author

kitknox commented Jan 13, 2026

@raggi The bug triggers on out[n] = '\x00' outside of the conditional when the condition is false. Reproduction from macOS below.

$ ./test_outofbounds
2026/01/12 17:17:33 tsnet running state path /Users/kit/Library/Application Support/tsnet-test_outofbounds/tailscaled.state
2026/01/12 17:17:33 tsnet starting with hostname "test_outofbounds", varRoot "/Users/kit/Library/Application Support/tsnet-test_outofbounds"
2026/01/12 17:17:33 LocalBackend state is NeedsLogin; running StartLoginInteractive...
...
panic: runtime error: index out of range [33] with length 33

goroutine 17 [running, locked to thread]:
main.TsnetErrmsg(0x7c000?, 0x1046d7ab0, 0x21)
tailscale.go:202 +0x1cc
Abort trap: 6 ./test_outofbounds

test_outofbounds.c

raggi added a commit that referenced this pull request Jan 13, 2026
- Fix bounds checking: check if copy() filled buffer (n >= len(out))
  instead of incorrect len(out) < len(src)-1 (thank you @kitknox / #45)
- Fix nil pointer dereference in 12 functions when getServer fails
- Fix syntax error in TsnetDial referencing undefined variable
- Simplify getServer to return *server instead of (*server, error)
  to avoid repetition of fixed bugs

Fixes #45
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.

3 participants