Re: Stream State and PRIORITY Frames

Cory Benfield <cory@lukasa.co.uk> Thu, 19 January 2017 14:15 UTC

Return-Path: <ietf-http-wg-request+bounce-httpbisa-archive-bis2juki=lists.ie@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 73E951270B4 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 19 Jan 2017 06:15:58 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -9.62
X-Spam-Level:
X-Spam-Status: No, score=-9.62 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_SORBS_SPAM=0.5, RP_MATCHES_RCVD=-3.199, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=lukasa-co-uk.20150623.gappssmtp.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PsL38cIja-Lt for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 19 Jan 2017 06:15:55 -0800 (PST)
Received: from frink.w3.org (frink.w3.org [128.30.52.56]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 9BAFF1295ED for <httpbisa-archive-bis2Juki@lists.ietf.org>; Thu, 19 Jan 2017 06:15:55 -0800 (PST)
Received: from lists by frink.w3.org with local (Exim 4.80) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1cUDRl-0007Pk-Mq for ietf-http-wg-dist@listhub.w3.org; Thu, 19 Jan 2017 14:12:13 +0000
Resent-Date: Thu, 19 Jan 2017 14:12:13 +0000
Resent-Message-Id: <E1cUDRl-0007Pk-Mq@frink.w3.org>
Received: from mimas.w3.org ([128.30.52.79]) by frink.w3.org with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <cory@lukasa.co.uk>) id 1cUDRi-0007Me-GB for ietf-http-wg@listhub.w3.org; Thu, 19 Jan 2017 14:12:10 +0000
Received: from mail-wm0-f50.google.com ([74.125.82.50]) by mimas.w3.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <cory@lukasa.co.uk>) id 1cUDRZ-0002Qs-7U for ietf-http-wg@w3.org; Thu, 19 Jan 2017 14:12:05 +0000
Received: by mail-wm0-f50.google.com with SMTP id c206so79162201wme.0 for <ietf-http-wg@w3.org>; Thu, 19 Jan 2017 06:11:40 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lukasa-co-uk.20150623.gappssmtp.com; s=20150623; h=mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=0qsGzY7iDtffKsuaq5CzAUa8zidXUiKLf1QK/bHvHiQ=; b=hdPghJihFb5eCUY5LEOfdyKQdrnQ/T2W8uvrZyxkxNj8xBmOVZmgOYqbmEJFZH9RvI K+3/2auqfxsymEnGZghVU5oF4is6wrTCtsibKiQ5++tZmr3UFEAEWDi37R7r0nO3wh5O SzBjehHZrHFvFSBaqutx6QDbQGCtwAgXHDf6e1KlqxcYv15V2iiSxpG3w0gPB1IHZqMc OXGJdIFXwLT/1CBi3IrnOci8MPTnwjSxPl603ZoIWbnBAiXb7Tql5AN3J76BCxsXqKhR ZTUsb73XublRLL1BdBhWALmHDdnSLuN3SfMnFA+hTM/HqPwAwys5vUaARcUZyIPc4PCr 1Qxg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=0qsGzY7iDtffKsuaq5CzAUa8zidXUiKLf1QK/bHvHiQ=; b=e1DqeZUPh9i6ci88lSvRKpcwTUMZDHrscbV7a+0xlMi8EXGlKR54UYoMRrBWS6frYI O1Enr5DF21Ai5qMXOk9CMXRDeEBmJteE3RlySphXarGeRtCU7pCrKvFSYI+kWt5kGfdo iI5I2qlenn9ENdMOq3Eews3bk2IUZVqIl7G8xG19ez3U1yoQTOAkgcALATcq0V1ESrmc Sd/Wy13z1iz3bCMG5RSwmUxY3LqoMQc2wpsOSwqD0IZhfDgfHzyKrwM4yApHx1KpduyV 96MAv/TC4PfzWaoBkXjLI2XtfMnZEoiPr9J+8fBFYIAAtBuxLyzQrXmoTop8f9jEzAtV 4URA==
X-Gm-Message-State: AIkVDXKpSBckTCe3sYP2HN836HLPS2FuGf2WX9ndaYeqTblwC+zybCz4DyTkji1zsE77zw==
X-Received: by 10.223.174.183 with SMTP id y52mr8563973wrc.112.1484835094365; Thu, 19 Jan 2017 06:11:34 -0800 (PST)
Received: from [192.168.1.3] (197.71.125.91.dyn.plus.net. [91.125.71.197]) by smtp.gmail.com with ESMTPSA id t194sm5916728wmd.1.2017.01.19.06.11.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Jan 2017 06:11:33 -0800 (PST)
Content-Type: text/plain; charset="utf-8"
Mime-Version: 1.0 (Mac OS X Mail 10.2 \(3259\))
From: Cory Benfield <cory@lukasa.co.uk>
In-Reply-To: <e420eda0-57fc-43e8-a82a-0988db75ab32@treenet.co.nz>
Date: Thu, 19 Jan 2017 14:11:31 +0000
Cc: ietf-http-wg@w3.org
Content-Transfer-Encoding: quoted-printable
Message-Id: <0FCBA000-E026-431A-802A-C2D39A98EF57@lukasa.co.uk>
References: <CAFn2buAYWHQSWhhoKZ2GKbqXR1A+tScjkAwZmOuQ9gV9jMp2bA@mail.gmail.com> <CAGZNdJWe0Y=M_SWmgYabKbWZwPEuJdw67Km8+UtR4oUtZuXA5A@mail.gmail.com> <2BC01E49-91A1-43A7-AFD0-5A34F2689428@lukasa.co.uk> <CAFn2buDCMwMp=rR0C_yt4-gUwyFhY6ruonz9wT-jVMu+Kir=nA@mail.gmail.com> <C51C3F51-37BE-489F-BA1D-76B101517307@lukasa.co.uk> <CAFn2buAE-EdTEG9x-wLQSy5Osmcq1Hdps9YLW_7j9CTV4_Fuyw@mail.gmail.com> <CANatvzzEV6Qd1huVxO=T2m7UwwX207RCetrXyZ1FMMGrBtzeEg@mail.gmail.com> <e420eda0-57fc-43e8-a82a-0988db75ab32@treenet.co.nz>
To: Amos Jeffries <squid3@treenet.co.nz>
X-Mailer: Apple Mail (2.3259)
Received-SPF: pass client-ip=74.125.82.50; envelope-from=cory@lukasa.co.uk; helo=mail-wm0-f50.google.com
X-W3C-Hub-Spam-Status: No, score=-3.6
X-W3C-Hub-Spam-Report: AWL=-0.157, BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_SORBS_SPAM=0.5, SPF_PASS=-0.001, W3C_AA=-1, W3C_WL=-1
X-W3C-Scan-Sig: mimas.w3.org 1cUDRZ-0002Qs-7U 5ae51afd7ba42e834b86f2608219f30f
X-Original-To: ietf-http-wg@w3.org
Subject: Re: Stream State and PRIORITY Frames
Archived-At: <http://www.w3.org/mid/0FCBA000-E026-431A-802A-C2D39A98EF57@lukasa.co.uk>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/33324
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <http://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>

> On 19 Jan 2017, at 09:00, Amos Jeffries <squid3@treenet.co.nz> wrote:
> 
> IIRC the intention behind the closing behaviour for idle streams was to
> ensure that we could optimize away the need to maintain a list or array
> of 2^31 state entries.
> 
> Omitting PRIORITY from the MAX_STREAMS voids that benefit.

No it doesn’t.

Firstly, let’s note that the PRIORITY frame is defined not to change stream state. Receiving a PRIORITY frame on stream N leaves it in the idle state. A server implementation can thus treat the receipt of a PRIORITY frame on any stream that has a higher ID than the last stream on which it received a HEADERS frame as having the *exact* same effect on state retention as receiving a PING frame. It doesn’t *require* the insertion of any stream state data.

Specific implementations may require the insertion of stream state data if priority information is stored on the same structure as stream state information, but that is certainly not required. For example, receiving a bunch of PRIORITY frames does not cause the Python HTTP/2 implementation to allocate any more state information than receiving a bunch of PING frames.

> It is causing state to be allocated on the server and on every
> intermediary along the way which accepts it.
> 
> Consider the effects of 2^31 PRIORITY frames being sent with different
> IDs before the first HEADERS is used.
> Notice how even this one case is markedly worse than sending just one
> HEADERS with stream ID == 2^31 to waste server sockets.

This problem is orthogonal to the one we’re discussing.

So far I haven’t seen a proposal to say that PRIORITY frames should transition a stream out of the idle state. If we continue to leave RFC 7540 saying that PRIORITY frames leave streams in the idle state, then definitionally they are excluded from the restrictions on MAX_CONCURRENT_STREAMS. So if you are allocating stream state for idle streams, then you are open to this DoS vector, but none of the proposals here are trying to address it.

Additionally, I should note that the unbounded insertion of priority information into priority trees was discussed as an attack vector in this paper: https://www.imperva.com/docs/Imperva_HII_HTTP2.pdf. The paper was published in August of last year, and several implementations took steps to reduce their vulnerability to it (the Python priority implementation even filed a CVE, CVE-2016-6580).

I absolutely support adding an erratum to indicate that implementations should resist unbounded insertion of PRIORITY information. But unless you’re willing to say that idle streams should be counted against MAX_CONCURRENT_STREAMS (which is a tricky thing to state), then the only way to resolve this problem at the spec level is to force PRIORITY frames to make state transitions, further complicating the state diagram for streams.

> What exactly does it mean for them to set PRIORITY on a non-existent stream?

It means exactly what RFC 7540 says it means. Quoting from Section 5.3.4 of RFC 7540:

> Similarly, streams that are in the "idle" state can be assigned priority or become a parent of other streams. This allows for the creation of a grouping node in the dependency tree, which enables more flexible expressions of priority. Idle streams begin with a default priority (Section 5.3.5).

While we’re here, right below that section is:

> The retention of priority information for streams that are not counted toward the limit set by SETTINGS_MAX_CONCURRENT_STREAMS could create a large state burden for an endpoint. Therefore, the amount of prioritization state that is retained MAY be limited.

To this end, the Python priority implementation allows a user-configured maximum amount of data retention for priority information. This priority information is held separately from stream state information because they are entirely orthogonal concerns: in fact, the bits of code that manage priority information and those that manage stream state information are in entirely separate installable packages with no dependency relationship to each other.

To my eye, there is a clear intent to allow setting of priority information on streams that are in the idle state, without that affecting the stream itself.

Cory