• Austin Clements's avatar
    runtime: avoid bad unwinding from sigpanic in C code · ddb503be
    Austin Clements authored
    Currently, if a sigpanic call is injected into C code, it's possible
    for preparePanic to leave the stack in a state where traceback can't
    unwind correctly past the sigpanic.
    
    Specifically, shouldPushPanic sniffs the stack to decide where to put
    the PC from the signal context. In the cgo case, it will find that
    !findfunc(pc).valid() because pc is in C code, and then it will check
    if the top of the stack looks like a Go PC. However, this stack slot
    is just in a C frame, so it could be uninitialized and contain
    anything, including what looks like a valid Go PC. For example, in
    https://build.golang.org/log/c601a18e2af24794e6c0899e05dddbb08caefc17,
    it sees 1c02c23a <runtime.newproc1+682>. When this condition is met,
    it skips putting the signal PC on the stack at all. As a result, when
    we later unwind from the sigpanic, we'll "successfully" but
    incorrectly unwind to whatever PC was in this uninitialized slot and
    go who knows where from there.
    
    Fix this by making shouldPushPanic assume that the signal PC is always
    usable if we're running C code, so we always make it appear like
    sigpanic's caller.
    
    This lets us be pickier again about unexpected return PCs in
    gentraceback.
    
    Updates #23640.
    
    Change-Id: I1e8ade24b031bd905d48e92d5e60c982e8edf160
    Reviewed-on: https://go-review.googlesource.com/91137
    Run-TryBot: Austin Clements <austin@google.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
    ddb503be
traceback.go 39.7 KB