runtime: handle underscore in Linux kernel release strings#170
Conversation
Some embedded Linux vendors append a platform identifier after an underscore in the uname release field. For example, Synology NVRs report a kernel release like "3.4.35_hi3535". parseRelease only stripped suffixes after '-' or '+', so the patch component "35_hi3535" failed to parse as an integer and the runtime threw "failed to parse kernel version from uname" before malloc heap initialization, making the program unbootable. Also strip everything after '_', mirroring the existing '-' and '+' handling. Regressed in f4de14a / CL 758902 on 2026-03-24, which started calling parseRelease unconditionally during osinit on 32-bit Linux to decide between 32- and 64-bit time syscalls. Updates golang#79612 Updates #162 Updates tailscale/tailscale#6860
creachadair
left a comment
There was a problem hiding this comment.
Just one non-blocking nit.
| // elided. | ||
| func parseRelease(rel string) (major, minor, patch int, ok bool) { | ||
| // Strip anything after a dash or plus. | ||
| // Strip anything after a dash, plus, or underscore. Some |
There was a problem hiding this comment.
The change seems fine, but we no longer actually follow semver grammar, strictly speaking (to be fair, Synology et al. started it). Maybe note this in the doc comment above? E.g.,
// parseRelease parses a dot-separated version number.
// It follows semver syntax, but allows the minor and patch
// versions to be elided, and accepts "_" as a separator for
// pre-release labels in addition to "-".or words to that effect.
(Likewise we don't handle build labels either, though if we got one of those on a kernel release we probably have bigger issues 😅)
There was a problem hiding this comment.
Strictly speaking, this code from Go (which is like 10 years old) never did semver... it also parse "4.5" without a patch.
There was a problem hiding this comment.
Yeah, I don't think we need to match the spec, my comment was mostly just about updating the comment. But it's unexported, so certainly not essential.
Some embedded Linux vendors append a platform identifier after an
underscore in the uname release field. For example, Synology NVRs
report a kernel release like "3.4.35_hi3535". parseRelease only
stripped suffixes after '-' or '+', so the patch component
"35_hi3535" failed to parse as an integer and the runtime threw
"failed to parse kernel version from uname" before malloc heap
initialization, making the program unbootable.
Also strip everything after '_', mirroring the existing '-' and '+'
handling.
Regressed in f4de14a / CL 758902 on 2026-03-24, which started
calling parseRelease unconditionally during osinit on 32-bit Linux
to decide between 32- and 64-bit time syscalls.
Updates golang#79612
Updates #162
Updates tailscale/tailscale#6860