Skip to content

Commit 77dd210

Browse files
committed
go: avoid possible read/modify/write of the Write window
The Write window is used to keep track of how much buffer space is free in the remote to avoid one connection blocking the rest. Previously we checked the window and decided how much to write, then dropped the metadata mutex before performing the write. In theory another Write call on the same connection could see that buffer size is free, send too much and block the connection. Therefore Write should take ownership of the space by bumping the `current` window before dropping the lock. Signed-off-by: David Scott <[email protected]>
1 parent ecc9379 commit 77dd210

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

go/pkg/libproxy/multiplexed.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,14 @@ func (c *channel) Write(p []byte) (int, error) {
138138
return written, io.EOF
139139
}
140140
if c.write.size() > 0 {
141+
// Some window space is available
141142
toWrite := c.write.size()
142143
if toWrite > len(p) {
143144
toWrite = len(p)
144145
}
146+
// Advance the window before dropping the lock in case another Write() appears and sees the same available space
147+
c.write.current = c.write.current + uint64(toWrite)
148+
145149
// Don't block holding the metadata mutex.
146150
// Note this would allow concurrent calls to Write on the same channel
147151
// to conflict, but we regard that as user error.
@@ -166,7 +170,6 @@ func (c *channel) Write(p []byte) (int, error) {
166170
if err3 != nil {
167171
return written, err3
168172
}
169-
c.write.current = c.write.current + uint64(toWrite)
170173
p = p[toWrite:]
171174
written = written + toWrite
172175
continue

0 commit comments

Comments
 (0)