Procházet zdrojové kódy

Temporary refraction-networking/gotapdance vendor patch

- Workaround for nil pointer dereference due to clearing or resetting cached
  registration TcpDialer
Rod Hynes před 3 roky
rodič
revize
2a4121d9a7

+ 15 - 3
vendor/github.com/refraction-networking/gotapdance/tapdance/conjure.go

@@ -108,7 +108,19 @@ func (r DecoyRegistrar) Register(cjSession *ConjureSession, ctx context.Context)
 	for _, decoy := range cjSession.RegDecoys {
 		Logger().Debugf("%v Sending Reg: %v, %v", cjSession.IDString(), decoy.GetHostname(), decoy.GetIpAddrStr())
 		//decoyAddr := decoy.GetIpAddrStr()
-		go reg.send(ctx, decoy, dialErrors, cjSession.registrationCallback)
+
+		// [Psiphon]
+		//
+		// Workaround: reference and pass in reg.TcpDialer rather than wait
+		// and reference it within reg.send in the goroutine. This allows
+		// gotapdance users to clear and reset the TcpDialer field for cached
+		// ConjureRegs without risking a race condition or nil pointer
+		// dereference. These conditions otherwise arise as reg.send
+		// goroutines can remain running, and reference reg.TcpDialer, after
+		// Register returns -- the point at which gotapdance users may cache
+		// the ConjureReg.
+
+		go reg.send(ctx, decoy, reg.TcpDialer, dialErrors, cjSession.registrationCallback)
 	}
 
 	//[reference] Dial errors happen immediately so block until all N dials complete
@@ -605,7 +617,7 @@ func (reg *ConjureReg) createRequest(tlsConn *tls.UConn, decoy *pb.TLSDecoySpec)
 }
 
 // Being called in parallel -> no changes to ConjureReg allowed in this function
-func (reg *ConjureReg) send(ctx context.Context, decoy *pb.TLSDecoySpec, dialError chan error, callback func(*ConjureReg)) {
+func (reg *ConjureReg) send(ctx context.Context, decoy *pb.TLSDecoySpec, dialer dialFunc, dialError chan error, callback func(*ConjureReg)) {
 
 	deadline, deadlineAlreadySet := ctx.Deadline()
 	if !deadlineAlreadySet {
@@ -618,7 +630,7 @@ func (reg *ConjureReg) send(ctx context.Context, decoy *pb.TLSDecoySpec, dialErr
 	tcpToDecoyStartTs := time.Now()
 
 	//[Note] decoy.GetIpAddrStr() will get only v4 addr if a decoy has both
-	dialConn, err := reg.TcpDialer(childCtx, "tcp", decoy.GetIpAddrStr())
+	dialConn, err := dialer(childCtx, "tcp", decoy.GetIpAddrStr())
 
 	reg.setTCPToDecoy(durationToU32ptrMs(time.Since(tcpToDecoyStartTs)))
 	if err != nil {