/[packages]/updates/8/varnish/current/SOURCES/82b0a629f60136e76112c6f2c6372cce77b683be.patch
ViewVC logotype

Contents of /updates/8/varnish/current/SOURCES/82b0a629f60136e76112c6f2c6372cce77b683be.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1737797 - (show annotations) (download)
Mon Jul 26 07:50:24 2021 UTC (2 years, 8 months ago) by neoclust
File size: 4582 byte(s)
Add P100: Fixes CVE-2021-36740 (mga#29290)
1 From 82b0a629f60136e76112c6f2c6372cce77b683be Mon Sep 17 00:00:00 2001
2 From: Martin Blix Grydeland <martin@varnish-software.com>
3 Date: Tue, 22 Jun 2021 11:47:55 +0200
4 Subject: [PATCH] Take content length into account on H/2 request bodies
5
6 When receiving H/2 data frames, make sure to take the advertised content
7 length into account, and fail appropriately if the combined sum of the
8 data frames does not match the content length.
9 ---
10 bin/varnishd/http2/cache_http2.h | 2 ++
11 bin/varnishd/http2/cache_http2_proto.c | 46 ++++++++++++++++++++------
12 2 files changed, 38 insertions(+), 10 deletions(-)
13
14 diff --git a/bin/varnishd/http2/cache_http2.h b/bin/varnishd/http2/cache_http2.h
15 index 270306d15c..c1456a6803 100644
16 --- a/bin/varnishd/http2/cache_http2.h
17 +++ b/bin/varnishd/http2/cache_http2.h
18 @@ -134,6 +134,8 @@ struct h2_req {
19 /* Where to wake this stream up */
20 struct worker *wrk;
21
22 + ssize_t reqbody_bytes;
23 +
24 VTAILQ_ENTRY(h2_req) tx_list;
25 h2_error error;
26 };
27 diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
28 index c079656b1b..59dd0336b5 100644
29 --- a/bin/varnishd/http2/cache_http2_proto.c
30 +++ b/bin/varnishd/http2/cache_http2_proto.c
31 @@ -554,6 +554,7 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2,
32 struct req *req, struct h2_req *r2)
33 {
34 h2_error h2e;
35 + ssize_t cl;
36
37 ASSERT_RXTHR(h2);
38 assert(r2->state == H2_S_OPEN);
39 @@ -574,16 +575,24 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2,
40 // XXX: Have I mentioned H/2 Is hodge-podge ?
41 http_CollectHdrSep(req->http, H_Cookie, "; "); // rfc7540,l,3114,3120
42
43 + cl = http_GetContentLength(req->http);
44 + assert(cl >= -2);
45 + if (cl == -2) {
46 + VSLb(h2->vsl, SLT_Debug, "Non-parseable Content-Length");
47 + return (H2SE_PROTOCOL_ERROR);
48 + }
49 +
50 if (req->req_body_status == NULL) {
51 - if (!http_GetHdr(req->http, H_Content_Length, NULL))
52 + if (cl == -1)
53 req->req_body_status = BS_EOF;
54 else
55 req->req_body_status = BS_LENGTH;
56 + req->htc->content_length = cl;
57 } else {
58 /* A HEADER frame contained END_STREAM */
59 assert (req->req_body_status == BS_NONE);
60 r2->state = H2_S_CLOS_REM;
61 - if (http_GetContentLength(req->http) > 0)
62 + if (cl > 0)
63 return (H2CE_PROTOCOL_ERROR); //rfc7540,l,1838,1840
64 }
65
66 @@ -737,6 +746,7 @@ h2_rx_data(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
67 int w1 = 0, w2 = 0;
68 char buf[4];
69 unsigned wi;
70 + ssize_t cl;
71
72 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
73 ASSERT_RXTHR(h2);
74 @@ -755,6 +765,23 @@ h2_rx_data(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
75 Lck_Unlock(&h2->sess->mtx);
76 return (h2->error ? h2->error : r2->error);
77 }
78 +
79 + r2->reqbody_bytes += h2->rxf_len;
80 + if (h2->rxf_flags & H2FF_DATA_END_STREAM)
81 + r2->state = H2_S_CLOS_REM;
82 + cl = r2->req->htc->content_length;
83 + if (cl >= 0 && (r2->reqbody_bytes > cl ||
84 + (r2->state >= H2_S_CLOS_REM && r2->reqbody_bytes != cl))) {
85 + VSLb(h2->vsl, SLT_Debug,
86 + "H2: stream %u: Received data and Content-Length"
87 + " mismatch", h2->rxf_stream);
88 + r2->error = H2SE_PROTOCOL_ERROR; // rfc7540,l,3150,3163
89 + if (r2->cond)
90 + AZ(pthread_cond_signal(r2->cond));
91 + Lck_Unlock(&h2->sess->mtx);
92 + return (H2SE_PROTOCOL_ERROR);
93 + }
94 +
95 AZ(h2->mailcall);
96 h2->mailcall = r2;
97 h2->req0->r_window -= h2->rxf_len;
98 @@ -773,6 +800,8 @@ h2_rx_data(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
99 r2->r_window += wi;
100 w2 = 1;
101 }
102 +
103 +
104 Lck_Unlock(&h2->sess->mtx);
105
106 if (w1 || w2) {
107 @@ -795,7 +824,7 @@ h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
108 struct h2_req *r2;
109 struct h2_sess *h2;
110 unsigned l;
111 - enum vfp_status retval = VFP_OK;
112 + enum vfp_status retval;
113
114 CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
115 CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
116 @@ -808,7 +837,6 @@ h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
117 *lp = 0;
118
119 Lck_Lock(&h2->sess->mtx);
120 - assert (r2->state == H2_S_OPEN);
121 r2->cond = &vc->wrk->cond;
122 while (h2->mailcall != r2 && h2->error == 0 && r2->error == 0)
123 AZ(Lck_CondWait(r2->cond, &h2->sess->mtx, 0));
124 @@ -831,12 +859,10 @@ h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
125 Lck_Unlock(&h2->sess->mtx);
126 return (VFP_OK);
127 }
128 - if (h2->rxf_len == 0) {
129 - if (h2->rxf_flags & H2FF_DATA_END_STREAM) {
130 - retval = VFP_END;
131 - r2->state = H2_S_CLOS_REM;
132 - }
133 - }
134 + if (h2->rxf_len == 0 && r2->state >= H2_S_CLOS_REM)
135 + retval = VFP_END;
136 + else
137 + retval = VFP_OK;
138 h2->mailcall = NULL;
139 AZ(pthread_cond_signal(h2->cond));
140 }

  ViewVC Help
Powered by ViewVC 1.1.30