family uint16
path [108]byte
}
-
-const __NEW_UTS_LEN = 64
-
-type new_utsname struct {
- sysname [__NEW_UTS_LEN + 1]byte
- nodename [__NEW_UTS_LEN + 1]byte
- release [__NEW_UTS_LEN + 1]byte
- version [__NEW_UTS_LEN + 1]byte
- machine [__NEW_UTS_LEN + 1]byte
- domainname [__NEW_UTS_LEN + 1]byte
-}
family uint16
path [108]byte
}
-
-const __NEW_UTS_LEN = 64
-
-type new_utsname struct {
- sysname [__NEW_UTS_LEN + 1]byte
- nodename [__NEW_UTS_LEN + 1]byte
- release [__NEW_UTS_LEN + 1]byte
- version [__NEW_UTS_LEN + 1]byte
- machine [__NEW_UTS_LEN + 1]byte
- domainname [__NEW_UTS_LEN + 1]byte
-}
var NetpollGenericInit = netpollGenericInit
-var ParseRelease = parseRelease
-
var Memmove = memmove
var MemclrNoHeapPointers = memclrNoHeapPointers
initsig(true)
}
-// gsignalInitQuirk, if non-nil, is called for every allocated gsignal G.
-//
-// TODO(austin): Remove this after Go 1.15 when we remove the
-// mlockGsignal workaround.
-var gsignalInitQuirk func(gsignal *g)
-
// Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) {
mp.gsignal = malg(32 * 1024) // Linux wants >= 2K
mp.gsignal.m = mp
- if gsignalInitQuirk != nil {
- gsignalInitQuirk(mp.gsignal)
- }
}
func gettid() uint32
package runtime
-import (
- "runtime/internal/atomic"
- "unsafe"
-)
-
-//go:noescape
-func uname(utsname *new_utsname) int
-
-func mlock(addr, len uintptr) int
-
-func osArchInit() {
- // Linux 5.2 introduced a bug that can corrupt vector
- // registers on return from a signal if the signal stack isn't
- // faulted in:
- // https://bugzilla.kernel.org/show_bug.cgi?id=205663
- //
- // It was fixed in 5.3.15, 5.4.2, and all 5.5 and later
- // kernels.
- //
- // If we're on an affected kernel, work around this issue by
- // mlocking the top page of every signal stack. This doesn't
- // help for signal stacks created in C, but there's not much
- // we can do about that.
- //
- // TODO(austin): Remove this in Go 1.15, at which point it
- // will be unlikely to encounter any of the affected kernels
- // in the wild.
-
- var uts new_utsname
- if uname(&uts) < 0 {
- throw("uname failed")
- }
- // Check for null terminator to ensure gostringnocopy doesn't
- // walk off the end of the release string.
- found := false
- for _, b := range uts.release {
- if b == 0 {
- found = true
- break
- }
- }
- if !found {
- return
- }
- rel := gostringnocopy(&uts.release[0])
-
- major, minor, patch, ok := parseRelease(rel)
- if !ok {
- return
- }
-
- if major == 5 && minor == 4 && patch < 2 {
- // All 5.4 versions of Ubuntu are patched.
- procVersion := []byte("/proc/version\000")
- f := open(&procVersion[0], _O_RDONLY, 0)
- if f >= 0 {
- var buf [512]byte
- p := noescape(unsafe.Pointer(&buf[0]))
- n := read(f, p, int32(len(buf)))
- closefd(f)
-
- needle := []byte("Ubuntu")
- contains:
- for i, c := range buf[:n] {
- if c != needle[0] {
- continue
- }
- if int(n)-i < len(needle) {
- break
- }
- for j, c2 := range needle {
- if c2 != buf[i+j] {
- continue contains
- }
- }
- // This is an Ubuntu system.
- return
- }
- }
- }
-
- if major == 5 && (minor == 2 || minor == 3 && patch < 15 || minor == 4 && patch < 2) {
- gsignalInitQuirk = mlockGsignal
- if m0.gsignal != nil {
- throw("gsignal quirk too late")
- }
- throwReportQuirk = throwBadKernel
- }
-}
-
-func mlockGsignal(gsignal *g) {
- if atomic.Load(&touchStackBeforeSignal) != 0 {
- // mlock has already failed, don't try again.
- return
- }
-
- // This mlock call may fail, but we don't report the failure.
- // Instead, if something goes badly wrong, we rely on prepareSignalM
- // and throwBadKernel to do further mitigation and to report a problem
- // to the user if mitigation fails. This is because many
- // systems have a limit on the total mlock size, and many kernels
- // that appear to have bad versions are actually patched to avoid the
- // bug described above. We want Go 1.14 to run on those systems.
- // See #37436.
- if errno := mlock(gsignal.stack.hi-physPageSize, physPageSize); errno < 0 {
- atomic.Store(&touchStackBeforeSignal, uint32(-errno))
- }
-}
-
-// throwBadKernel is called, via throwReportQuirk, by throw.
-func throwBadKernel() {
- if errno := atomic.Load(&touchStackBeforeSignal); errno != 0 {
- println("runtime: note: your Linux kernel may be buggy")
- println("runtime: note: see https://golang.org/wiki/LinuxKernelSignalVectorBug")
- println("runtime: note: mlock workaround for kernel bug failed with errno", errno)
- }
-}
+func osArchInit() {}
}
}
-// throwReportQuirk, if non-nil, is called by throw after dumping the stacks.
-//
-// TODO(austin): Remove this after Go 1.15 when we remove the
-// mlockGsignal workaround.
-var throwReportQuirk func()
-
var didothers bool
var deadlock mutex
printDebugLog()
- if throwReportQuirk != nil {
- throwReportQuirk()
- }
-
return docrash
}
b[n2] = 0 // for luck
return s[:n2]
}
-
-// parseRelease parses a dot-separated version number. It follows the
-// semver syntax, but allows the minor and patch versions to be
-// elided.
-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 := func() (int, bool) {
- for i := 0; i < len(rel); i++ {
- if rel[i] == '.' {
- ver, ok := atoi(rel[:i])
- rel = rel[i+1:]
- return ver, ok
- }
- }
- ver, ok := atoi(rel)
- rel = ""
- return ver, ok
- }
- if major, ok = next(); !ok || rel == "" {
- return
- }
- if minor, ok = next(); !ok || rel == "" {
- return
- }
- patch, ok = next()
- return
-}
}
}
}
-
-type parseReleaseTest struct {
- in string
- major, minor, patch int
-}
-
-var parseReleaseTests = []parseReleaseTest{
- {"", -1, -1, -1},
- {"x", -1, -1, -1},
- {"5", 5, 0, 0},
- {"5.12", 5, 12, 0},
- {"5.12-x", 5, 12, 0},
- {"5.12.1", 5, 12, 1},
- {"5.12.1-x", 5, 12, 1},
- {"5.12.1.0", 5, 12, 1},
- {"5.20496382327982653440", -1, -1, -1},
-}
-
-func TestParseRelease(t *testing.T) {
- for _, test := range parseReleaseTests {
- major, minor, patch, ok := runtime.ParseRelease(test.in)
- if !ok {
- major, minor, patch = -1, -1, -1
- }
- if test.major != major || test.minor != minor || test.patch != patch {
- t.Errorf("parseRelease(%q) = (%v, %v, %v) want (%v, %v, %v)",
- test.in, major, minor, patch,
- test.major, test.minor, test.patch)
- }
- }
-}
#define SYS_socketcall 102
#define SYS_setittimer 104
#define SYS_clone 120
-#define SYS_uname 122
-#define SYS_mlock 150
#define SYS_sched_yield 158
#define SYS_nanosleep 162
#define SYS_rt_sigreturn 173
INVOKE_SYSCALL
MOVL AX, ret+0(FP)
RET
-
-// func uname(utsname *new_utsname) int
-TEXT ·uname(SB),NOSPLIT,$0-8
- MOVL $SYS_uname, AX
- MOVL utsname+0(FP), BX
- INVOKE_SYSCALL
- MOVL AX, ret+4(FP)
- RET
-
-// func mlock(addr, len uintptr) int
-TEXT ·mlock(SB),NOSPLIT,$0-12
- MOVL $SYS_mlock, AX
- MOVL addr+0(FP), BX
- MOVL len+4(FP), CX
- INVOKE_SYSCALL
- MOVL AX, ret+8(FP)
- RET
#define SYS_clone 56
#define SYS_exit 60
#define SYS_kill 62
-#define SYS_uname 63
#define SYS_fcntl 72
#define SYS_sigaltstack 131
-#define SYS_mlock 149
#define SYS_arch_prctl 158
#define SYS_gettid 186
#define SYS_futex 202
SYSCALL
MOVQ AX, ret+0(FP)
RET
-
-// func uname(utsname *new_utsname) int
-TEXT ·uname(SB),NOSPLIT,$0-16
- MOVQ utsname+0(FP), DI
- MOVL $SYS_uname, AX
- SYSCALL
- MOVQ AX, ret+8(FP)
- RET
-
-// func mlock(addr, len uintptr) int
-TEXT ·mlock(SB),NOSPLIT,$0-24
- MOVQ addr+0(FP), DI
- MOVQ len+8(FP), SI
- MOVL $SYS_mlock, AX
- SYSCALL
- MOVQ AX, ret+16(FP)
- RET