runtime: revert signal stack mlocking

Go 1.14 included a (rather awful) workaround for a Linux kernel bug
that corrupted vector registers on x86 CPUs during signal delivery
(https://bugzilla.kernel.org/show_bug.cgi?id=205663). This bug was
introduced in Linux 5.2 and fixed in 5.3.15, 5.4.2 and all 5.5 and
later kernels. The fix was also back-ported by major distros. This
workaround was necessary, but had unfortunate downsides, including
causing Go programs to exceed the mlock ulimit in many configurations
(#37436).

We're reasonably confident that by the Go 1.16 release, the number of
systems running affected kernels will be vanishingly small. Hence,
this CL removes this workaround.

This effectively reverts CLs 209597 (version parser), 209899 (mlock
top of signal stack), 210299 (better failure message), 223121 (soft
mlock failure handling), and 244059 (special-case patched Ubuntu
kernels). The one thing we keep is the osArchInit function. It's empty
everywhere now, but is a reasonable hook to have.

Updates #35326, #35777 (the original register corruption bugs).
Updates #40184 (request to revert in 1.15).
Fixes #35979.

Change-Id: Ie213270837095576f1f3ef46bf3de187dc486c50
Reviewed-on: https://go-review.googlesource.com/c/go/+/246200
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
index f4db8cf..64a0fbc 100644
--- a/src/runtime/defs_linux_386.go
+++ b/src/runtime/defs_linux_386.go
@@ -226,14 +226,3 @@
 	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
-}
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
index 8480d85..1ae18a3 100644
--- a/src/runtime/defs_linux_amd64.go
+++ b/src/runtime/defs_linux_amd64.go
@@ -262,14 +262,3 @@
 	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
-}
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 5ab03f3..d591fdc 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -43,8 +43,6 @@
 
 var NetpollGenericInit = netpollGenericInit
 
-var ParseRelease = parseRelease
-
 var Memmove = memmove
 var MemclrNoHeapPointers = memclrNoHeapPointers
 
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 7b95ff2..22931b4 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -328,20 +328,11 @@
 	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
diff --git a/src/runtime/os_linux_x86.go b/src/runtime/os_linux_x86.go
index 97f8707..d91fa1a 100644
--- a/src/runtime/os_linux_x86.go
+++ b/src/runtime/os_linux_x86.go
@@ -7,120 +7,4 @@
 
 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() {}
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 615249f..127843b 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -1283,12 +1283,6 @@
 	}
 }
 
-// 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
 
@@ -1335,10 +1329,6 @@
 
 	printDebugLog()
 
-	if throwReportQuirk != nil {
-		throwReportQuirk()
-	}
-
 	return docrash
 }
 
diff --git a/src/runtime/string.go b/src/runtime/string.go
index 0515b56..2510442 100644
--- a/src/runtime/string.go
+++ b/src/runtime/string.go
@@ -499,37 +499,3 @@
 	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
-}
diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go
index b9ac667..4eda12c 100644
--- a/src/runtime/string_test.go
+++ b/src/runtime/string_test.go
@@ -454,34 +454,3 @@
 		}
 	}
 }
-
-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)
-		}
-	}
-}
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
index 5b9b638..1e3a834 100644
--- a/src/runtime/sys_linux_386.s
+++ b/src/runtime/sys_linux_386.s
@@ -39,8 +39,6 @@
 #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
@@ -808,20 +806,3 @@
 	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
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index fe9c6bc..b60057c 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -33,10 +33,8 @@
 #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
@@ -789,20 +787,3 @@
 	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