[go/release-branch.go1.26] runtime: tolerate vendor suffixes in Linux kernel release strings

3 views
Skip to first unread message

Jorropo (Gerrit)

unread,
Jun 24, 2026, 1:58:51 PM (3 days ago) Jun 24
to goph...@pubsubhelper.golang.org, Brad Fitzpatrick, golang-co...@googlegroups.com

Jorropo has uploaded the change for review

Commit message

runtime: tolerate vendor suffixes in Linux kernel release strings

Synology kernels can have a "_" in their uname version. Make the
parsing more tolerant. And also don't throw during init if we fail to
parse the kernel version. Instead, fall back to probing. (We can't
probe all the time, because seccomp filters on some platforms like
Android kill the process if we call a verbotenen system call)

This regressed in CL 758902 (forked from CL 751340) on 2026-03-24,
which started calling parseRelease unconditionally during osinit on
32-bit Linux.

Fixes #79893
Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69

Change diff

diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go
index 52afd28..f8c4b4f 100644
--- a/src/runtime/export_linux_test.go
+++ b/src/runtime/export_linux_test.go
@@ -11,6 +11,7 @@

var NewOSProc0 = newosproc0
var Mincore = mincore
+var ParseRelease = parseRelease

type Siginfo siginfo
type Sigevent sigevent
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 493567b..0474e6c 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -943,53 +943,66 @@
}

// getKernelVersion returns major and minor kernel version numbers
-// parsed from the uname release field.
-func getKernelVersion() kernelVersion {
+// parsed from the uname release field. ok reports whether parsing
+// succeeded; on failure callers must pick a default rather than
+// failing, because this is called during osinit before the runtime
+// is fully initialized and a throw here is unrecoverable.
+func getKernelVersion() (kv kernelVersion, ok bool) {
var buf linux.Utsname
if e := linux.Uname(&buf); e != 0 {
- throw("uname failed")
+ return kernelVersion{}, false
}
-
rel := gostringnocopy(&buf.Release[0])
major, minor, _, ok := parseRelease(rel)
if !ok {
- throw("failed to parse kernel version from uname")
+ return kernelVersion{}, false
}
- return kernelVersion{major: major, minor: minor}
+ return kernelVersion{major: major, minor: minor}, true
}

-// parseRelease parses a dot-separated version number. It follows the
-// semver syntax, but allows the minor and patch versions to be
-// elided.
+// parseRelease parses a dot-separated version number from the prefix
+// of rel. It returns ok=true only if at least the major and minor
+// components were successfully parsed; the patch component is
+// best-effort. Trailing vendor or build suffixes such as
+// "-generic", "+", "_hi3535", or "-rc1" are ignored.
func parseRelease(rel string) (major, minor, patch int, ok bool) {
- // Strip anything after a dash or plus.
- for i := 0; i < len(rel); i++ {
- if rel[i] == '-' || rel[i] == '+' {
- rel = rel[:i]
- break
+ // next consumes a run of decimal digits from the front of rel,
+ // returning the parsed value. If the digits are followed by a
+ // '.', it is consumed and more is set so the caller knows to
+ // parse another component; otherwise scanning terminates and
+ // the rest of rel is discarded.
+ next := func() (n int, more, ok bool) {
+ i := 0
+ for i < len(rel) && rel[i] >= '0' && rel[i] <= '9' {
+ i++
}
+ if i == 0 {
+ return 0, false, false
+ }
+ n, err := strconv.Atoi(rel[:i])
+ if err != nil {
+ return 0, false, false
+ }
+ if i < len(rel) && rel[i] == '.' {
+ rel = rel[i+1:]
+ return n, true, true
+ }
+ rel = ""
+ return n, false, true
}

- next := func() (int, bool) {
- for i := 0; i < len(rel); i++ {
- if rel[i] == '.' {
- ver, err := strconv.Atoi(rel[:i])
- rel = rel[i+1:]
- return ver, err == nil
- }
- }
- ver, err := strconv.Atoi(rel)
- rel = ""
- return ver, err == nil
+ var more bool
+ if major, more, ok = next(); !ok || !more {
+ return 0, 0, 0, false
}
- if major, ok = next(); !ok || rel == "" {
- return
+ if minor, more, ok = next(); !ok {
+ return 0, 0, 0, false
}
- if minor, ok = next(); !ok || rel == "" {
- return
+ if !more {
+ return major, minor, 0, true
}
- patch, ok = next()
- return
+ patch, _, _ = next()
+ return major, minor, patch, true
}

// GE checks if the running kernel version
diff --git a/src/runtime/os_linux32.go b/src/runtime/os_linux32.go
index 1ee1cdc..ff437ce 100644
--- a/src/runtime/os_linux32.go
+++ b/src/runtime/os_linux32.go
@@ -10,8 +10,38 @@
"unsafe"
)

+// configure64bitsTimeOn32BitsArchitectures decides whether to use the
+// 64-bit time variants of futex and timer_settime on 32-bit Linux.
+//
+// The choice is normally made by parsing the kernel release string
+// from uname, because probing with -ENOSYS misbehaves on some
+// kernels: Android 8.0-10 (API 26-29) has a seccomp filter that kills
+// the process on unknown syscalls instead of returning -ENOSYS, and
+// some older Synology kernels reuse the new syscall numbers for
+// unrelated vendor syscalls, which silently runs the wrong thing.
+//
+// If the kernel release string can't be parsed, fall back to probing
+// futex_time64 with a no-op FUTEX_WAKE: the kernels that motivated
+// the version check above all report parseable uname strings, so
+// reaching the probing fallback generally means we are on neither,
+// and probing is the safest available signal.
func configure64bitsTimeOn32BitsArchitectures() {
- use64bitsTimeOn32bits = getKernelVersion().GE(5, 1)
+ if kv, ok := getKernelVersion(); ok {
+ use64bitsTimeOn32bits = kv.GE(5, 1)
+ return
+ }
+ use64bitsTimeOn32bits = probeFutexTime64()
+}
+
+// probeFutexTime64 reports whether the futex_time64 syscall is
+// available on the running kernel. It issues a FUTEX_WAKE_PRIVATE
+// with a wake count of 0, which is a no-op if the syscall exists and
+// returns -ENOSYS otherwise. timer_settime64 was added to the kernel
+// in the same release (Linux 5.1), so a single probe covers both.
+func probeFutexTime64() bool {
+ var word uint32
+ ret := futex_time64(unsafe.Pointer(&word), _FUTEX_WAKE_PRIVATE, 0, nil, nil, 0)
+ return ret != -_ENOSYS
}

//go:noescape
diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go
index ab2452c..728d65a 100644
--- a/src/runtime/runtime_linux_test.go
+++ b/src/runtime/runtime_linux_test.go
@@ -53,6 +53,36 @@
}
}

+func TestParseRelease(t *testing.T) {
+ tests := []struct {
+ in string
+ major, minor, patch int
+ ok bool
+ }{
+ {"6.1.0", 6, 1, 0, true},
+ {"5.15.0-91-generic", 5, 15, 0, true},
+ {"4.19.0+", 4, 19, 0, true},
+ {"6.6.0-rc1", 6, 6, 0, true},
+ // Synology embedded Linux appends a platform identifier
+ // after an underscore.
+ {"3.4.35_hi3535", 3, 4, 35, true},
+ {"2.6.32_synology", 2, 6, 32, true},
+ {"3.10", 3, 10, 0, true},
+ // A single component is not enough; major+minor required.
+ {"3", 0, 0, 0, false},
+ {"3-rc1", 0, 0, 0, false},
+ {"", 0, 0, 0, false},
+ {"bogus", 0, 0, 0, false},
+ }
+ for _, tt := range tests {
+ major, minor, patch, ok := ParseRelease(tt.in)
+ if major != tt.major || minor != tt.minor || patch != tt.patch || ok != tt.ok {
+ t.Errorf("ParseRelease(%q) = (%d, %d, %d, %v); want (%d, %d, %d, %v)",
+ tt.in, major, minor, patch, ok, tt.major, tt.minor, tt.patch, tt.ok)
+ }
+ }
+}
+
func TestKernelStructSize(t *testing.T) {
// Check that the Go definitions of structures exchanged with the kernel are
// the same size as what the kernel defines.

Change information

Files:
  • M src/runtime/export_linux_test.go
  • M src/runtime/os_linux.go
  • M src/runtime/os_linux32.go
  • M src/runtime/runtime_linux_test.go
Change size: M
Delta: 4 files changed, 106 insertions(+), 32 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedMatching-Subject-Prefix
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: go
Gerrit-Branch: release-branch.go1.26
Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
Gerrit-Change-Number: 793960
Gerrit-PatchSet: 1
Gerrit-Owner: Jorropo <jorro...@gmail.com>
Gerrit-Reviewer: Jorropo <jorro...@gmail.com>
Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
unsatisfied_requirement
satisfied_requirement
open
diffy

Jorropo (Gerrit)

unread,
Jun 24, 2026, 1:59:40 PM (3 days ago) Jun 24
to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Jorropo uploaded new patchset

Jorropo uploaded patch set #2 to this change.
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: newpatchset
    Gerrit-Project: go
    Gerrit-Branch: release-branch.go1.26
    Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
    Gerrit-Change-Number: 793960
    Gerrit-PatchSet: 2
    Gerrit-Owner: Jorropo <jorro...@gmail.com>
    Gerrit-Reviewer: Jorropo <jorro...@gmail.com>
    Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Michael Pratt (Gerrit)

    unread,
    Jun 26, 2026, 3:58:33 PM (15 hours ago) Jun 26
    to Jorropo, Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Michael Pratt, Damien Neil, Keith Randall, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
    Attention needed from Damien Neil, Dmitri Shuralyov, Jorropo and Keith Randall

    Michael Pratt added 2 comments

    Commit Message
    Line 19, Patchset 2 (Latest):Fixes #79893
    Michael Pratt . unresolved

    Please keep "Updates #79612", in addition to this new issue.
    ```suggestion
    Updates #79612
    Fixes #79893
    ```

    Line 22, Patchset 2 (Latest):
    Michael Pratt . unresolved

    Usually we keep all of the other Gerrit footers here, but I'm not sure if it actually matters. @dmit...@golang.org do you know?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Damien Neil
    • Dmitri Shuralyov
    • Jorropo
    • Keith Randall
    Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: go
      Gerrit-Branch: release-branch.go1.26
      Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
      Gerrit-Change-Number: 793960
      Gerrit-PatchSet: 2
      Gerrit-Owner: Jorropo <jorro...@gmail.com>
      Gerrit-Reviewer: Damien Neil <dn...@google.com>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Jorropo <jorro...@gmail.com>
      Gerrit-Reviewer: Keith Randall <k...@golang.org>
      Gerrit-Reviewer: Michael Pratt <mpr...@google.com>
      Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Attention: Keith Randall <k...@golang.org>
      Gerrit-Attention: Jorropo <jorro...@gmail.com>
      Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Attention: Damien Neil <dn...@google.com>
      Gerrit-Comment-Date: Fri, 26 Jun 2026 19:58:27 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy

      Dmitri Shuralyov (Gerrit)

      unread,
      Jun 26, 2026, 8:09:09 PM (11 hours ago) Jun 26
      to Jorropo, Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Michael Pratt, Damien Neil, Keith Randall, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
      Attention needed from Jorropo

      Dmitri Shuralyov added 1 comment

      Commit Message
      Michael Pratt . resolved

      Usually we keep all of the other Gerrit footers here, but I'm not sure if it actually matters. @dmit...@golang.org do you know?

      Dmitri Shuralyov

      Yes, the other Gerrit footers are usually kept - this is covered at https://go.dev/wiki/MinorReleases#making-cherry-pick-cls:

      In the popup enter the branch name (like release-branch.go1.10), add the commit message prefix (like [release-branch.go1.10]), update the “Fixes” line and _do not change any of the other automated lines._

      (Emphasis mine.)

      It would be okay to add them, but I don't think it matters too much if on occasion, such as this CL, they're missed. If someone needs to look them up, those original footers are available at the original upstream CL.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Jorropo
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: go
      Gerrit-Branch: release-branch.go1.26
      Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
      Gerrit-Change-Number: 793960
      Gerrit-PatchSet: 2
      Gerrit-Owner: Jorropo <jorro...@gmail.com>
      Gerrit-Reviewer: Damien Neil <dn...@google.com>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Jorropo <jorro...@gmail.com>
      Gerrit-Reviewer: Keith Randall <k...@golang.org>
      Gerrit-Reviewer: Michael Pratt <mpr...@google.com>
      Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Attention: Jorropo <jorro...@gmail.com>
      Gerrit-Comment-Date: Sat, 27 Jun 2026 00:09:03 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Michael Pratt <mpr...@google.com>
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy

      Jorropo (Gerrit)

      unread,
      Jun 26, 2026, 11:27:04 PM (7 hours ago) Jun 26
      to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
      Attention needed from Jorropo

      Jorropo uploaded new patchset

      Jorropo uploaded patch set #3 to this change.
      Open in Gerrit

      Related details

      Attention is currently required from:
      • Jorropo
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: newpatchset
      Gerrit-Project: go
      Gerrit-Branch: release-branch.go1.26
      Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
      Gerrit-Change-Number: 793960
      Gerrit-PatchSet: 3
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy

      Jorropo (Gerrit)

      unread,
      Jun 26, 2026, 11:28:47 PM (7 hours ago) Jun 26
      to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
      Attention needed from Jorropo

      Jorropo uploaded new patchset

      Jorropo uploaded patch set #4 to this change.
      Open in Gerrit

      Related details

      Attention is currently required from:
      • Jorropo
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: newpatchset
      Gerrit-Project: go
      Gerrit-Branch: release-branch.go1.26
      Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
      Gerrit-Change-Number: 793960
      Gerrit-PatchSet: 4
      unsatisfied_requirement
      satisfied_requirement
      open
      diffy

      Jorropo (Gerrit)

      unread,
      Jun 26, 2026, 11:29:05 PM (7 hours ago) Jun 26
      to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Michael Pratt, Damien Neil, Keith Randall, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
      Attention needed from Dmitri Shuralyov and Michael Pratt

      Jorropo added 2 comments

      Commit Message
      Line 19, Patchset 2:Fixes #79893
      Michael Pratt . resolved

      Please keep "Updates #79612", in addition to this new issue.
      ```suggestion
      Updates #79612
      Fixes #79893
      ```

      Michael Pratt . resolved

      Usually we keep all of the other Gerrit footers here, but I'm not sure if it actually matters. @dmit...@golang.org do you know?

      Dmitri Shuralyov

      Yes, the other Gerrit footers are usually kept - this is covered at https://go.dev/wiki/MinorReleases#making-cherry-pick-cls:

      In the popup enter the branch name (like release-branch.go1.10), add the commit message prefix (like [release-branch.go1.10]), update the “Fixes” line and _do not change any of the other automated lines._

      (Emphasis mine.)

      It would be okay to add them, but I don't think it matters too much if on occasion, such as this CL, they're missed. If someone needs to look them up, those original footers are available at the original upstream CL.

      Jorropo

      Done

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Dmitri Shuralyov
      • Michael Pratt
      Submit Requirements:
        • requirement is not satisfiedCode-Review
        • requirement satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        • requirement is not satisfiedTryBots-Pass
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: go
        Gerrit-Branch: release-branch.go1.26
        Gerrit-Change-Id: I98f61b94e54c7b9d08029f3aef664bdda9ec7f69
        Gerrit-Change-Number: 793960
        Gerrit-PatchSet: 4
        Gerrit-Owner: Jorropo <jorro...@gmail.com>
        Gerrit-Reviewer: Damien Neil <dn...@google.com>
        Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
        Gerrit-Reviewer: Jorropo <jorro...@gmail.com>
        Gerrit-Reviewer: Keith Randall <k...@golang.org>
        Gerrit-Reviewer: Michael Pratt <mpr...@google.com>
        Gerrit-CC: Brad Fitzpatrick <brad...@golang.org>
        Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
        Gerrit-Attention: Michael Pratt <mpr...@google.com>
        Gerrit-Comment-Date: Sat, 27 Jun 2026 03:28:58 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Dmitri Shuralyov <dmit...@golang.org>
        Comment-In-Reply-To: Michael Pratt <mpr...@google.com>
        unsatisfied_requirement
        satisfied_requirement
        open
        diffy
        Reply all
        Reply to author
        Forward
        0 new messages