bufio.CachedConn: data race on the cached buffer between Read/ReaderReplaceable and Close
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 55/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- go
- Área
- networking
Línea de trabajo
Start in common/bufio/cache.go with CachedConn.Read, ReaderReplaceable, Close, and the corresponding CachedPacketConn methods. Reproduce the reported concurrent paths with the race detector, including the routing and DNS-over-TCP entry points named in the issue. Done means the cache has one consistent ownership path, without races or double release.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
sing v0.8.10 (via sing-box v1.13.12), go 1.26, -race
CachedConn.buffer is read and cleared without synchronization in Read and ReaderReplaceable, while Close (usually called from another goroutine) reads and clears it too. Close guards itself with taken, but Read / ReaderReplaceable don't check or set taken:
// common/bufio/cache.go
func (c *CachedConn) Read(p []byte) (n int, err error) {
if c.buffer != nil { // read
...
c.buffer.DecRef()
c.buffer.Release()
c.buffer = nil // write
}
return c.Conn.Read(p)
}
func (c *CachedConn) ReaderReplaceable() bool {
return c.buffer == nil // read
}
func (c *CachedConn) Close() error {
if c.taken.CompareAndSwap(false, true) {
if buffer := c.buffer; buffer != nil { // read (races with Read)
c.buffer = nil
buffer.DecRef()
buffer.Release() // can release a buffer Read already released
}
}
return c.Conn.Close()
}
CachedPacketConn.ReadPacket / Close have the same pattern.
Besides the race report, the worst case is the pooled buffer being released twice, so it can come back from buf.New to another connection while still referenced.
Where it shows up in sing-box 1.13.12 (both found with -race):
- Routing a sniffed TCP connection:
route.(*Router).routeConnectionwraps it inbufio.NewCachedConn;ConnectionManager.connectionCopythen callsReaderReplaceable(viaN.UnwrapCountReaderinbufio.CopyWithCounters) on one goroutine, while the other copy direction callsClose(route/conn.go:262 vs :271). - Hijacked DNS over TCP:
protocol/dns.HandleStreamDNSRequestreads the next query from the conn (handle.go:24) while the exchange goroutine of the previous query callsconn.Close()on error (handle.go:46).
When the wrapper can be unwrapped before copying, ReadCached (which does use taken) avoids it, but callers such as a ConnectionTracker that wraps the conn force the unsynchronized Read path.
Suggested fix: make every consumer of the cache take it through the same atomic flag, e.g.
func (c *CachedConn) Read(p []byte) (n int, err error) {
if !c.taken.Load() {
c.mu.Lock() // or take the buffer once with CompareAndSwap and keep it reader-local
...
}
return c.Conn.Read(p)
}
or have Read take the buffer once (CompareAndSwap(false, true)), move it into a reader-owned field, and never touch it from Close after that. ReaderReplaceable would then read an atomic. Happy to send a PR if the approach sounds right.
- Lenguaje dominante
- Go
- Estrellas
- 131
- Forks
- 116
- Merge medio
- 1 h 42 min
- PR fusionados (30 d)
- 1
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de SagerNet/sing
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
-
socks握手时的bufio会吞掉客户端流水线发送的首段payload,进而导致UoT v2客户端的每条流都会失败Posiblemente ocupada @Snowy117 la tomó hace 13 días. Abierto
Dificultad 4/5 1-2 días Aptitud para principiantes 48/100
-
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
-
addr 相关的几个问题Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 42/100
-
Dificultad 3/5 1-2 días Aptitud para principiantes 30/100
Todos los issues de SagerNet/sing
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
dataiku/kiji-proxy#635 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
hyperledger-firefly/signer#126 ·
-
agent-review-finding chore
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
jordansmall/spindrift#5748 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
-
Resource links written as host:port without a scheme are brokenPosiblemente ocupada @RaphaelFakhri la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día