Commit 053c93cd authored by Dag Haavi Finstad's avatar Dag Haavi Finstad

Enforce sequence requirement of header block frames

This commit enforces that a HEADERS frame without an END_HEADERS flag
must be followed by a CONTINUATION frame on the same stream.

Sending interleaved/out of sequence header or continuation frames will
now be treated as a PROTOCOL_ERROR, as per rfc7540.

This also fixes the panics seen in #2387.

Fixes: #2387
parent 993ca79e
......@@ -508,7 +508,7 @@ h2_do_req(struct worker *wrk, void *priv)
}
static h2_error
h2_end_headers(struct worker *wrk, const struct h2_sess *h2,
h2_end_headers(struct worker *wrk, struct h2_sess *h2,
struct req *req, struct h2_req *r2)
{
h2_error h2e;
......@@ -518,6 +518,7 @@ h2_end_headers(struct worker *wrk, const struct h2_sess *h2,
h2e = h2h_decode_fini(h2, r2->decode);
FREE_OBJ(r2->decode);
r2->state = H2_S_CLOS_REM;
h2->new_req = NULL;
if (h2e != NULL) {
Lck_Lock(&h2->sess->mtx);
VSLb(h2->vsl, SLT_Debug, "HPACK/FINI %s", h2e->name);
......@@ -614,9 +615,7 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
return (0);
}
/**********************************************************************
* XXX: Check hard sequence req. for Cont.
*/
/**********************************************************************/
static h2_error __match_proto__(h2_frame_f)
h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
......@@ -831,6 +830,11 @@ h2_procframe(struct worker *wrk, struct h2_sess *h2,
AN(r2);
}
if (h2->new_req != NULL &&
!(h2->new_req == r2->req && h2f == H2_F_CONTINUATION))
return (H2CE_PROTOCOL_ERROR); // rfc7540,l,1859,1863
h2e = h2f->rxfunc(wrk, h2, r2);
if (h2e == 0)
return (0);
......
varnishtest "2387: Crash on out of order header blocks"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {} -start
varnish v1 -cliok "param.set feature +http2"
varnish v1 -cliok "param.set debug +syncvsl"
barrier b1 cond 2
barrier b2 cond 2
client c1 {
stream 1 {
txreq -nohdrend
barrier b2 sync
barrier b1 sync
txcont -hdr "bar" "foo"
} -start
stream 3 {
barrier b2 sync
txreq -nohdrend
barrier b1 sync
txcont -hdr "bar" "foo"
} -run
stream 0 {
rxgoaway
expect goaway.laststream == "3"
expect goaway.err == PROTOCOL_ERROR
} -run
} -run
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment