summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch131
1 files changed, 131 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch b/meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch
new file mode 100644
index 0000000000..ebdc5aec6d
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.12/CVE-2020-15586.patch
@@ -0,0 +1,131 @@
1From fa98f46741f818913a8c11b877520a548715131f Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Mon, 13 Jul 2020 13:27:22 -0400
4Subject: [PATCH] net/http: synchronize "100 Continue" write and Handler writes
5
6The expectContinueReader writes to the connection on the first
7Request.Body read. Since a Handler might be doing a read in parallel or
8before a write, expectContinueReader needs to synchronize with the
9ResponseWriter, and abort if a response already went out.
10
11The tests will land in a separate CL.
12
13Fixes #34902
14Fixes CVE-2020-15586
15
16Change-Id: Icdd8dd539f45e8863762bd378194bb4741e875fc
17Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/793350
18Reviewed-by: Filippo Valsorda <valsorda@google.com>
19Reviewed-on: https://go-review.googlesource.com/c/go/+/242598
20Run-TryBot: Katie Hockman <katie@golang.org>
21Reviewed-by: Filippo Valsorda <filippo@golang.org>
22TryBot-Result: Gobot Gobot <gobot@golang.org>
23
24Upstream-Status: Backport
25CVE: CVE-2020-15586
26Signed-off-by: Li Zhou <li.zhou@windriver.com>
27---
28 src/net/http/server.go | 43 +++++++++++++++++++++++++++++++++++-------
29 1 file changed, 36 insertions(+), 7 deletions(-)
30
31diff --git a/src/net/http/server.go b/src/net/http/server.go
32index a995a50658..d41b5f6f48 100644
33--- a/src/net/http/server.go
34+++ b/src/net/http/server.go
35@@ -425,6 +425,16 @@ type response struct {
36 wants10KeepAlive bool // HTTP/1.0 w/ Connection "keep-alive"
37 wantsClose bool // HTTP request has Connection "close"
38
39+ // canWriteContinue is a boolean value accessed as an atomic int32
40+ // that says whether or not a 100 Continue header can be written
41+ // to the connection.
42+ // writeContinueMu must be held while writing the header.
43+ // These two fields together synchronize the body reader
44+ // (the expectContinueReader, which wants to write 100 Continue)
45+ // against the main writer.
46+ canWriteContinue atomicBool
47+ writeContinueMu sync.Mutex
48+
49 w *bufio.Writer // buffers output in chunks to chunkWriter
50 cw chunkWriter
51
52@@ -515,6 +525,7 @@ type atomicBool int32
53
54 func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
55 func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
56+func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
57
58 // declareTrailer is called for each Trailer header when the
59 // response header is written. It notes that a header will need to be
60@@ -878,21 +889,27 @@ type expectContinueReader struct {
61 resp *response
62 readCloser io.ReadCloser
63 closed bool
64- sawEOF bool
65+ sawEOF atomicBool
66 }
67
68 func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
69 if ecr.closed {
70 return 0, ErrBodyReadAfterClose
71 }
72- if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
73- ecr.resp.wroteContinue = true
74- ecr.resp.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
75- ecr.resp.conn.bufw.Flush()
76+ w := ecr.resp
77+ if !w.wroteContinue && w.canWriteContinue.isSet() && !w.conn.hijacked() {
78+ w.wroteContinue = true
79+ w.writeContinueMu.Lock()
80+ if w.canWriteContinue.isSet() {
81+ w.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
82+ w.conn.bufw.Flush()
83+ w.canWriteContinue.setFalse()
84+ }
85+ w.writeContinueMu.Unlock()
86 }
87 n, err = ecr.readCloser.Read(p)
88 if err == io.EOF {
89- ecr.sawEOF = true
90+ ecr.sawEOF.setTrue()
91 }
92 return
93 }
94@@ -1311,7 +1328,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
95 // because we don't know if the next bytes on the wire will be
96 // the body-following-the-timer or the subsequent request.
97 // See Issue 11549.
98- if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF {
99+ if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.isSet() {
100 w.closeAfterReply = true
101 }
102
103@@ -1561,6 +1578,17 @@ func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err er
104 }
105 return 0, ErrHijacked
106 }
107+
108+ if w.canWriteContinue.isSet() {
109+ // Body reader wants to write 100 Continue but hasn't yet.
110+ // Tell it not to. The store must be done while holding the lock
111+ // because the lock makes sure that there is not an active write
112+ // this very moment.
113+ w.writeContinueMu.Lock()
114+ w.canWriteContinue.setFalse()
115+ w.writeContinueMu.Unlock()
116+ }
117+
118 if !w.wroteHeader {
119 w.WriteHeader(StatusOK)
120 }
121@@ -1872,6 +1900,7 @@ func (c *conn) serve(ctx context.Context) {
122 if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
123 // Wrap the Body reader with one that replies on the connection
124 req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
125+ w.canWriteContinue.setTrue()
126 }
127 } else if req.Header.get("Expect") != "" {
128 w.sendExpectationFailed()
129--
1302.17.1
131