Uma expressão regular consome 100% da CPU global

Cloudflare · 2 de julho de 2019

Impacto: 27 minutos de queda global. Todo o tráfego HTTP/HTTPS da rede passou a responder erro 502.

O que aconteceu

Uma regra nova do firewall de aplicação foi publicada para toda a rede. Ela continha uma expressão regular destinada a detectar scripts maliciosos em requisições.

A expressão tinha um padrão com aninhamento de quantificadores — do tipo .*.*=.* — que, diante de certas entradas, faz o motor de regex explorar um número exponencial de caminhos antes de desistir. É o que se chama de retrocesso catastrófico.

Como o firewall roda em cada máquina da borda e a regra foi distribuída globalmente em segundos, todos os núcleos de todos os servidores da rede foram para 100% de CPU quase ao mesmo tempo. Sem CPU sobrando, nada era servido.

A recuperação exigiu desativar globalmente o módulo do firewall — o que só foi possível porque existia um interruptor global para isso.

A linha do tempo

  1. T+0

    Regra nova de firewall publicada globalmente, em poucos segundos.

  2. T+~1min

    O retrocesso catastrófico leva a CPU a 100% em toda a rede de borda simultaneamente.

  3. T+3min

    Tráfego global começa a responder 502.

  4. T+~14min

    Causa identificada como o módulo de firewall.

  5. T+27min

    Módulo desativado globalmente; tráfego volta.

A causa raiz

A causa imediata foi a regex. A causa raiz foi o processo de publicação: uma mudança de regra ia de zero a cem por cento da rede em segundos, sem estágio intermediário e sem teto de consumo de CPU por regra. Uma mudança que atinge tudo ao mesmo tempo não tem como falhar pequeno.

Antes do incidente

O que você colocaria na pilha para conter o estrago?

O que mudou depois

  • A publicação de regras passou a ser progressiva, com estágios e observação entre eles.
  • Foi adicionado limite de CPU por regra, para que uma regra ruim falhe sozinha.
  • Regexes passaram a ser analisadas em busca de padrões com risco de retrocesso exponencial antes da publicação.

Fonte: Cloudflare — *Details of the Cloudflare outage on July 2, 2019*, por John Graham-Cumming