TUN-5836: Avoid websocket#Stream function from crashing cloudflared with unexpected memory access

This commit is contained in:
Nuno Diegues 2022-03-04 16:22:17 +00:00
parent 5c6207debc
commit 9d9627f645
1 changed files with 18 additions and 5 deletions

View File

@ -12,6 +12,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/getsentry/raven-go"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@ -72,13 +73,25 @@ func unidirectionalStream(dst io.Writer, src io.Reader, dir string, status *bidi
// close. In such case, if the other direction did not stop (due to application level stopping, e.g., if a // close. In such case, if the other direction did not stop (due to application level stopping, e.g., if a
// server/origin listens forever until closure), it may read/write from the underlying ReadWriter (backed by // server/origin listens forever until closure), it may read/write from the underlying ReadWriter (backed by
// the Edge<->cloudflared transport) in an unexpected state. // the Edge<->cloudflared transport) in an unexpected state.
// Because of this, we set this recover() logic.
if status.isAnyDone() {
// Because of this, we set this recover() logic, which kicks-in *only* if any stream is known to have
// exited. In such case, we stop a possible panic from propagating upstream.
if r := recover(); r != nil { if r := recover(); r != nil {
if status.isAnyDone() {
// We handle such unexpected errors only when we detect that one side of the streaming is done. // We handle such unexpected errors only when we detect that one side of the streaming is done.
log.Debug().Msgf("Gracefully handled error %v in Streaming for %s, error %s", r, dir, debug.Stack()) log.Debug().Msgf("Gracefully handled error %v in Streaming for %s, error %s", r, dir, debug.Stack())
} else {
// Otherwise, this is unexpected, but we prevent the program from crashing anyway.
log.Warn().Msgf("Gracefully handled unexpected error %v in Streaming for %s, error %s", r, dir, debug.Stack())
tags := make(map[string]string)
tags["root"] = "websocket.stream"
tags["dir"] = dir
switch rval := r.(type) {
case error:
raven.CaptureError(rval, tags)
default:
rvalStr := fmt.Sprint(rval)
raven.CaptureMessage(rvalStr, tags)
}
} }
} }
}() }()