@@ -52,10 +52,11 @@ import (
52
52
)
53
53
54
54
const (
55
- prefaceTimeout = 10 * time .Second
56
- firstSettingsTimeout = 2 * time .Second // should be in-flight with preface anyway
57
- handlerChunkWriteSize = 4 << 10
58
- defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
55
+ prefaceTimeout = 10 * time .Second
56
+ firstSettingsTimeout = 2 * time .Second // should be in-flight with preface anyway
57
+ handlerChunkWriteSize = 4 << 10
58
+ defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
59
+ maxQueuedControlFrames = 10000
59
60
)
60
61
61
62
var (
@@ -163,6 +164,15 @@ func (s *Server) maxConcurrentStreams() uint32 {
163
164
return defaultMaxStreams
164
165
}
165
166
167
+ // maxQueuedControlFrames is the maximum number of control frames like
168
+ // SETTINGS, PING and RST_STREAM that will be queued for writing before
169
+ // the connection is closed to prevent memory exhaustion attacks.
170
+ func (s * Server ) maxQueuedControlFrames () int {
171
+ // TODO: if anybody asks, add a Server field, and remember to define the
172
+ // behavior of negative values.
173
+ return maxQueuedControlFrames
174
+ }
175
+
166
176
type serverInternalState struct {
167
177
mu sync.Mutex
168
178
activeConns map [* serverConn ]struct {}
@@ -506,6 +516,7 @@ type serverConn struct {
506
516
sawFirstSettings bool // got the initial SETTINGS frame after the preface
507
517
needToSendSettingsAck bool
508
518
unackedSettings int // how many SETTINGS have we sent without ACKs?
519
+ queuedControlFrames int // control frames in the writeSched queue
509
520
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
510
521
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
511
522
curClientStreams uint32 // number of open streams initiated by the client
@@ -894,6 +905,14 @@ func (sc *serverConn) serve() {
894
905
}
895
906
}
896
907
908
+ // If the peer is causing us to generate a lot of control frames,
909
+ // but not reading them from us, assume they are trying to make us
910
+ // run out of memory.
911
+ if sc .queuedControlFrames > sc .srv .maxQueuedControlFrames () {
912
+ sc .vlogf ("http2: too many control frames in send queue, closing connection" )
913
+ return
914
+ }
915
+
897
916
// Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
898
917
// with no error code (graceful shutdown), don't start the timer until
899
918
// all open streams have been completed.
@@ -1093,6 +1112,14 @@ func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
1093
1112
}
1094
1113
1095
1114
if ! ignoreWrite {
1115
+ if wr .isControl () {
1116
+ sc .queuedControlFrames ++
1117
+ // For extra safety, detect wraparounds, which should not happen,
1118
+ // and pull the plug.
1119
+ if sc .queuedControlFrames < 0 {
1120
+ sc .conn .Close ()
1121
+ }
1122
+ }
1096
1123
sc .writeSched .Push (wr )
1097
1124
}
1098
1125
sc .scheduleFrameWrite ()
@@ -1210,10 +1237,8 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
1210
1237
// If a frame is already being written, nothing happens. This will be called again
1211
1238
// when the frame is done being written.
1212
1239
//
1213
- // If a frame isn't being written we need to send one, the best frame
1214
- // to send is selected, preferring first things that aren't
1215
- // stream-specific (e.g. ACKing settings), and then finding the
1216
- // highest priority stream.
1240
+ // If a frame isn't being written and we need to send one, the best frame
1241
+ // to send is selected by writeSched.
1217
1242
//
1218
1243
// If a frame isn't being written and there's nothing else to send, we
1219
1244
// flush the write buffer.
@@ -1241,6 +1266,9 @@ func (sc *serverConn) scheduleFrameWrite() {
1241
1266
}
1242
1267
if ! sc .inGoAway || sc .goAwayCode == ErrCodeNo {
1243
1268
if wr , ok := sc .writeSched .Pop (); ok {
1269
+ if wr .isControl () {
1270
+ sc .queuedControlFrames --
1271
+ }
1244
1272
sc .startFrameWrite (wr )
1245
1273
continue
1246
1274
}
@@ -1533,6 +1561,8 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
1533
1561
if err := f .ForeachSetting (sc .processSetting ); err != nil {
1534
1562
return err
1535
1563
}
1564
+ // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be
1565
+ // acknowledged individually, even if multiple are received before the ACK.
1536
1566
sc .needToSendSettingsAck = true
1537
1567
sc .scheduleFrameWrite ()
1538
1568
return nil
0 commit comments