Przeglądaj źródła

Recover from panics within udpgw input processing

Rod Hynes 9 lat temu
rodzic
commit
6e7ff7d602
3 zmienionych plików z 16 dodań i 4 usunięć
  1. 2 2
      psiphon/server/api.go
  2. 1 1
      psiphon/server/safetyNet.go
  3. 13 1
      psiphon/server/udp.go

+ 2 - 2
psiphon/server/api.go

@@ -83,8 +83,8 @@ func dispatchAPIRequestHandler(
 	name string,
 	params requestJSONObject) (response []byte, reterr error) {
 
-	// Recover from and log any unexpected panics causes by user input
-	// handling bugs. User inputs shuld be properly validated; this
+	// Recover from and log any unexpected panics caused by user input
+	// handling bugs. User inputs should be properly validated; this
 	// mechanism is only a last resort to prevent the process from
 	// terminating in the case of a bug.
 	defer func() {

+ 1 - 1
psiphon/server/safetyNet.go

@@ -104,7 +104,7 @@ type jwtBody struct {
 	// exist and the default values assigned when
 	// unmarshalling into the corresponding non-pointer
 	// struct would cause non-existing fields to be logged
-	// in a manner that would make it impossible to distinguise
+	// in a manner that would make it impossible to distinguish
 	// between a non-existing field and field of default value
 	BasicIntegrity             *bool     `json:"basicIntegrity"`
 	CtsProfileMatch            *bool     `json:"ctsProfileMatch"`

+ 13 - 1
psiphon/server/udp.go

@@ -25,6 +25,7 @@ import (
 	"fmt"
 	"io"
 	"net"
+	"runtime/debug"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -100,6 +101,17 @@ func (mux *udpPortForwardMultiplexer) run() {
 	// When the client disconnects or the server shuts down, the channel will close and
 	// readUdpgwMessage will exit with EOF.
 
+	// Recover from and log any unexpected panics caused by udpgw input handling bugs.
+	// Note: this covers the run() goroutine only and not relayDownstream() goroutines.
+	defer func() {
+		if e := recover(); e != nil {
+			err := common.ContextError(
+				fmt.Errorf(
+					"udpPortForwardMultiplexer panic: %s: %s", e, debug.Stack()))
+			log.WithContextFields(LogFields{"error": err}).Warning("run failed")
+		}
+	}()
+
 	buffer := make([]byte, udpgwProtocolMaxMessageSize)
 	for {
 		// Note: message.packet points to the reusable memory in "buffer".
@@ -305,7 +317,7 @@ func (portForward *udpPortForward) relayDownstream() {
 		if err != nil {
 			if err != io.EOF {
 				// Debug since errors such as "use of closed network connection" occur during normal operation
-				log.WithContextFields(LogFields{"error": err}).Warning("downstream UDP relay failed")
+				log.WithContextFields(LogFields{"error": err}).Debug("downstream UDP relay failed")
 			}
 			break
 		}