From b8eda642a795cd25930c53a978f2cb677d10aa65 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Wed, 15 Nov 2017 09:46:32 -0500 Subject: [PATCH] Splunk: limit the reader size on error responses Before this patch, if a splunk endpoint returned a non-OK status, the splunk driver would read the entire response body. This could lead to excessive memory allocations. Instead put a cap on the amount the driver will read from the response body. Signed-off-by: Brian Goff Upstream-commit: 7f14542ddd1401de734be3ac0331c0ada941c959 Component: engine --- .../engine/daemon/logger/splunk/splunk.go | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/components/engine/daemon/logger/splunk/splunk.go b/components/engine/daemon/logger/splunk/splunk.go index eb80a0b526..30ab7b7414 100644 --- a/components/engine/daemon/logger/splunk/splunk.go +++ b/components/engine/daemon/logger/splunk/splunk.go @@ -22,6 +22,7 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/loggerutils" + "github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/urlutil" "github.com/sirupsen/logrus" ) @@ -55,6 +56,8 @@ const ( defaultBufferMaximum = 10 * defaultPostMessagesBatchSize // Number of messages allowed to be queued in the channel defaultStreamChannelSize = 4 * defaultPostMessagesBatchSize + // maxResponseSize is the max amount that will be read from an http response + maxResponseSize = 1024 ) const ( @@ -500,20 +503,22 @@ func (l *splunkLogger) tryPostMessages(ctx context.Context, messages []*splunkMe if l.gzipCompression { req.Header.Set("Content-Encoding", "gzip") } - res, err := l.client.Do(req) + resp, err := l.client.Do(req) if err != nil { return err } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - var body []byte - body, err = ioutil.ReadAll(res.Body) + defer func() { + pools.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() + if resp.StatusCode != http.StatusOK { + rdr := io.LimitReader(resp.Body, maxResponseSize) + body, err := ioutil.ReadAll(rdr) if err != nil { return err } - return fmt.Errorf("%s: failed to send event - %s - %s", driverName, res.Status, body) + return fmt.Errorf("%s: failed to send event - %s - %s", driverName, resp.Status, string(body)) } - io.Copy(ioutil.Discard, res.Body) return nil } @@ -596,20 +601,22 @@ func verifySplunkConnection(l *splunkLogger) error { if err != nil { return err } - res, err := l.client.Do(req) + resp, err := l.client.Do(req) if err != nil { return err } - if res.Body != nil { - defer res.Body.Close() - } - if res.StatusCode != http.StatusOK { - var body []byte - body, err = ioutil.ReadAll(res.Body) + defer func() { + pools.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() + + if resp.StatusCode != http.StatusOK { + rdr := io.LimitReader(resp.Body, maxResponseSize) + body, err := ioutil.ReadAll(rdr) if err != nil { return err } - return fmt.Errorf("%s: failed to verify connection - %s - %s", driverName, res.Status, body) + return fmt.Errorf("%s: failed to verify connection - %s - %s", driverName, resp.Status, string(body)) } return nil }