SIGSEGV processing with recovery?

The signal packet indicates:

Synchronous signals are signals caused by errors in the execution program: SIGBUS, SIGFPE and SIGSEGV. They are considered only synchronously when triggered by the execution of a program, and not when sent using os.Process.Kill or a kill program or similar mechanism. In general, with the exception of the cases discussed below, Go programs convert a synchronous signal during a pause.

However, it seems that recover() does not understand this.

Program:

 package main import ( "fmt" "unsafe" "log" ) func seeAnotherDay() { defer func() { if p := recover(); p != nil { err := fmt.Errorf("recover panic: panic call") log.Println(err) return } }() panic("oops") } func notSoMuch() { defer func() { if p := recover(); p != nil { err := fmt.Errorf("recover panic: sigseg") log.Println(err) return } }() b := make([]byte, 1) log.Println("access some memory") foo := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(9999999999999999))) fmt.Print(*foo + 1) } func main() { seeAnotherDay() notSoMuch() } 

Output:

 2017/04/04 12:13:16 recover panic: panic call 2017/04/04 12:13:16 access some memory unexpected fault address 0xb01dfacedebac1e fatal error: fault [signal SIGSEGV: segmentation violation code=0x1 addr=0xb01dfacedebac1e pc=0x108aa8a] goroutine 1 [running]: runtime.throw(0x10b5807, 0x5) /usr/local/go/src/runtime/panic.go:596 +0x95 fp=0xc420043ea8 sp=0xc420043e88 runtime.sigpanic() /usr/local/go/src/runtime/signal_unix.go:297 +0x28c fp=0xc420043ef8 sp=0xc420043ea8 main.notSoMuch() /Users/kbrandt/src/sigseg/main.go:32 +0xca fp=0xc420043f78 sp=0xc420043ef8 main.main() /Users/kbrandt/src/sigseg/main.go:37 +0x25 fp=0xc420043f88 sp=0xc420043f78 runtime.main() /usr/local/go/src/runtime/proc.go:185 +0x20a fp=0xc420043fe0 sp=0xc420043f88 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc420043fe8 sp=0xc420043fe0 exit status 2 

Is there any way to handle SIGSEGV so that it is localized in certain parts of the code?

+5
source share
1 answer

When you come across sigsegv, you really are in a lot of betting situations regarding the state of the program. The only thing that is generally safe is to stop everything, and perhaps the system will upload your memory to a debug file, which is what Go does. In this situation, there is no way to "protect the main runtime."

If you have a runtime environment that executes untrusted or insecure code, you must isolate it in a separate process. And if you use code received from users (and not the users themselves), this process should definitely be isolated.

So my advice, do one of the following:

  • Let it work and let the user process it from there. The user code that calls sigsegv on Go usually requires more or less active attempts to fire in the direction of one leg, so it should be rare and possibly served under what they do at their own peril and risk in any case.
  • Divide it into the supervisor process and the child process "untrustworthy", in which the supervisor selects the wrong exit conditions for the child process and reports accordingly.
+1
source

Source: https://habr.com/ru/post/1266324/


All Articles