11月 162017
 

Varnishの複数のバージョンがリリースされました。 [changelog] [パッケージDL] [ソースDL]

今回のリリースはセキュリティ対策によるもので、なるだけ迅速にアップデート、もしくは回避するために設定を見直す必要があります。
詳しくは公式情報(VSV00002)を参照してください。

脆弱性の内容

以下の条件を満たす際にsegfault/データリークが発生する可能性があります。

  • VCL_backend_errorで生成したsyntheticオブジェクト(beresp.body)を
  • file/persistentストレージに挿入する
原因

バックエンドへの接続が失敗したりなどで表示されるエラー画面はvcl_backend_errorで生成されています。
builtin.vclをみればわかるようにこのアクション内でエラー画面を生成しています。
で、この生成したものを後処理でストレージを確保してからberesp.bodyからストレージへmemcpy(3)するんですが、この際にfile/persistentストレージがターゲットに選ばれた際に問題が発生します。
file/persistentストレージの領域はpage-sizeでalignされており、確保サイズが割り切れない場合はちょっと余分な容量がついてきます。
で、この時にmemcpy(3)の第三引数に指定するサイズをalignされたサイズをそのまま渡してしまったために、コピー元から余分なサイズをreadしようとしてしまいます(なのでだいたいはsegfaultするかと)

では、vcl_backend_errorを通過すると必ず起きるかというとそうでもないです。
このようなエラー画面などは、TTLが短いためtransientというテンポラリストレージに保存するようになっています。
これは明示的に指定していない場合はmallocストレージエンジンが利用されるので今回のケースには当てはまりません。
しかし、transientに挿入する条件はエラー画面だからとかそういうのではなく、純粋にTTL(正確にはttl+grace+keepの合計値)がパラメータのshortlived未満かどうかです。
shortlivedを超える場合はhintで指定された(無指定はdefault)ストレージを使用します。
そして、shortlivedはデフォルトで10秒なので、VCL_backend_errorにおいてttlがそれ以上になるようにしていると引っかかります。(そのような人は珍しい気もしますが・・)
では、そのまま使っているケースであれば踏まないかというと、実は踏むケースが存在します。
ここのコードを見てみると同一リクエストがある状態(waitinglistに入ってる)の場合だとttl+grace+keepの合計が11secになります。
デフォルトのshortlivedが10secなのでここにタッチしますので、この状態でdefault storageがfile/persistentを使用している場合は踏んでしまいます。
なのでまとめるとこんな感じになります

Transientを明示的にfile/persistent指定している場合(ex -sTransient=file…)
vcl_backend_errorに突入した場合は引っかかります。
そもそもTransientをfile/persistentで使うメリットはそこまで無いので再検討するとよいかと思います。

デフォルトストレージにfile/persistent指定している場合
このケースでは2パタンあります。
vcl_backend_errorでTTL/grace/keepを明示的に指定していて、合計値がshortlived以上の場合はvcl_backend_errorに突入した場合は引っかかります。
次にTTLの変更もなく、shortlivedの変更もない(default 10sec)場合で同一リクエストがラッシュしてる状態だとTTL合計値がshortlivedを超えるためvcl_backend_errorに突入した場合は引っかかります。

なお、同様にsyntheticオブジェクトを生成するvcl_synthのほうは影響を受けません。
vcl_synthの場合はここでmemcpy(3)していますが、resp.bodyのlength(szl)を利用していますので問題ありません。

暫定の回避方法

それぞれの設定によって違いますが、説明したとおりとりあえずvcl_backend_errorでfile/persistentストレージが使われなければOKです。
なのでvcl_backend_errorもshortlivedもいじってない場合はshortlivedを12sに設定するかvcl_backend_errorでのTTL/grace/keep指定を明示的に0にすると良いでしょう。
なお、shortlivedを引き上げた場合はメモリの使用状況が変わるのでモニタリングする必要がありますし、TTLを明示的に0にした場合は若干ラッシュ時のオリジンの耐性が弱くなるでしょう。(気にするレベルではないと思います)
まぁどちらにせよ早めにアップデートするのが良いでしょう。

そのほかの変更について

今回はこの脆弱性以外にもいくつか修正があります。

4.1.9/5.2.1共通の変更
バグ修正

クライアントからのリクエストが空っぽの場合にidle_timeoutが正しく使用されなかったのを修正(#2492)

4.1.9のみの変更

基本的に5.2.0にあるもののbackportになります

新機能

bereq.is_bgfetchの追加
req.ttlの評価変更(#2422)

バグ修正

いくつかのカウンタの修正