github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/runtime/os_linux_x86.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build linux
     6  // +build 386 amd64
     7  
     8  package runtime
     9  
    10  //go:noescape
    11  func uname(utsname *new_utsname) int
    12  
    13  func mlock(addr, len uintptr) int
    14  
    15  func osArchInit() {
    16  	// Linux 5.2 introduced a bug that can corrupt vector
    17  	// registers on return from a signal if the signal stack isn't
    18  	// faulted in:
    19  	// https://bugzilla.kernel.org/show_bug.cgi?id=205663
    20  	//
    21  	// It was fixed in 5.3.15, 5.4.2, and all 5.5 and later
    22  	// kernels.
    23  	//
    24  	// If we're on an affected kernel, work around this issue by
    25  	// mlocking the top page of every signal stack. This doesn't
    26  	// help for signal stacks created in C, but there's not much
    27  	// we can do about that.
    28  	//
    29  	// TODO(austin): Remove this in Go 1.15, at which point it
    30  	// will be unlikely to encounter any of the affected kernels
    31  	// in the wild.
    32  
    33  	var uts new_utsname
    34  	if uname(&uts) < 0 {
    35  		throw("uname failed")
    36  	}
    37  	// Check for null terminator to ensure gostringnocopy doesn't
    38  	// walk off the end of the release string.
    39  	found := false
    40  	for _, b := range uts.release {
    41  		if b == 0 {
    42  			found = true
    43  			break
    44  		}
    45  	}
    46  	if !found {
    47  		return
    48  	}
    49  	rel := gostringnocopy(&uts.release[0])
    50  
    51  	major, minor, patch, ok := parseRelease(rel)
    52  	if !ok {
    53  		return
    54  	}
    55  
    56  	if major == 5 && (minor == 2 || minor == 3 && patch < 15 || minor == 4 && patch < 2) {
    57  		gsignalInitQuirk = mlockGsignal
    58  		if m0.gsignal != nil {
    59  			throw("gsignal quirk too late")
    60  		}
    61  	}
    62  }
    63  
    64  func mlockGsignal(gsignal *g) {
    65  	if err := mlock(gsignal.stack.hi-physPageSize, physPageSize); err < 0 {
    66  		printlock()
    67  		println("runtime: mlock of signal stack failed:", -err)
    68  		if err == -_ENOMEM {
    69  			println("runtime: increase the mlock limit (ulimit -l) or")
    70  		}
    71  		println("runtime: update your kernel to 5.3.15+, 5.4.2+, or 5.5+")
    72  		throw("mlock failed")
    73  	}
    74  }