Reptar: vulnerabilidade FSRM/REX em CPUs Intel
(lock.cmpxchg8b.com)- Em alguns processadores Intel, quando
rep movse um prefixorex.rduplicado interagem com a otimização FSRM, a CPU pode entrar em um estado de “glitch” que foge das regras normais - A causa está na decodificação flexível de prefixos do x86 e no fato de que, em instruções que usam operandos implícitos, como
movsb, um prefixorexque originalmente deveria não ter significado acaba seguindo um determinado caminho de otimização - Em agosto de 2023, o pipeline de validação do Google encontrou resultados imprevisíveis nessa combinação e observou desvios inesperados, desvios incondicionais ignorados e anomalias no registro do ponteiro de instrução em
xsaveecall - Se vários núcleos acionarem o mesmo bug ao mesmo tempo, podem ocorrer uma machine check exception e a parada do sistema; como isso também é reproduzível dentro de uma VM convidada sem privilégios, é importante para ambientes de nuvem
- A Intel publicou uma atualização de microcódigo para os processadores afetados; quando a atualização não é possível, é possível desativar fast strings em
IA32_MISC_ENABLE, mas isso traz uma grande queda de desempenho
Prefixos x86 e rep movsb
rep movsbé uma forma idiomática de mover memória em x86: ao definir origem, destino, direção e contador, o processador cuida da cópia repetida- A instrução real é
movsb, erepé um prefixo que altera essa instrução para que ela seja repetida várias vezes - A decodificação de instruções x86 é relativamente flexível, então prefixos sem significado ou conflitantes geralmente são ignorados
- Compiladores podem usar esses prefixos redundantes para preencher uma única instrução até o limite de alinhamento desejado
rex,vexeevexsão prefixos que alteram a forma como a instrução seguinte é decodificada
A combinação problemática com o prefixo rex
- O i386 tinha 8 registradores de uso geral, então era possível especificar registradores com 3 bits, mas o x86-64 tem 16 registradores de uso geral e precisa de bits adicionais
- O prefixo
rexfornece bits extras que a instrução seguinte pode tomar emprestados ao codificar operandos- Normalmente é escrito como
rex.rxb, com os bitsb,x,rewdefinidos opcionalmente
- Normalmente é escrito como
- Como
movsbnão explicita operandos na instrução e todos eles são implícitos, os bitsrexemrex.rxb rep movsbnão deveriam ter significado - Em geral, o processador simplesmente ignora esse prefixo
rex, mas em sistemas com suporte a fast short repeat move essa combinação leva a uma vulnerabilidade
FSRM e processadores afetados
- FSRM é um recurso introduzido no Ice Lake que complementa a limitação do ERMS no tratamento de strings curtas
- ERMS (enhanced repeat move/store) pode tornar o código
rep movsbexistente mais rápido ao tratar o alinhamento do buffer e stores largos no microcódigo- Como o custo inicial de configuração é alto, ele não é adequado para strings muito curtas
- FSRM é um recurso para processar mais rapidamente movimentações curtas de até 128 bytes
- É possível verificar o suporte pela flag
fsrmna linhaflagsde/proc/cpuinfo - Exemplos de processadores que incluem FSRM:
- Ice Lake
- Rocket Lake
- Tiger Lake
- Raptor Lake
- Alder Lake
- Sapphire Rapids
- Esta lista não é abrangente; para a lista completa, consulte o advisory da Intel INTEL-SA-00950
Descoberta e reprodução
- O pipeline de validação do Google executa duas formas de programas gerados aleatoriamente usando a técnica de Oracle Serialization e depois compara se o estado final é o mesmo
- Há uma explicação relacionada no post anterior Oracle Serialization
- Em agosto de 2023, resultados imprevisíveis ocorreram ao adicionar um prefixo
rex.rduplicado arep movsotimizado por FSRM - Os comportamentos anômalos observados foram:
- Desvio para um local inesperado
- Desvio incondicional ignorado
- Ponteiro de instrução (instruction pointer) não registrado corretamente em instruções
xsaveoucall - Depurador relatando um estado impossível
- Quando vários núcleos acionam o mesmo bug, o processador pode relatar uma machine check exception e parar
- Como é reproduzível também dentro de uma VM convidada sem privilégios, isso se torna um problema de segurança importante para provedores de nuvem
- A ferramenta de reprodução e o material de pesquisa foram publicados no repositório de pesquisas de segurança do Google
- Um espelho local da ferramenta
icebreaktambém é fornecido como icebreak.tar.gz
- Um espelho local da ferramenta
icebreaktenta reproduzir o problema especificando diferentes pares de núcleos- Em sistemas não afetados, não deve haver saída, como em um loop infinito
- Em sistemas afetados, um
.é exibido a cada reprodução bem-sucedida - Em núcleos irmãos SMT, podem ser observados desvios aleatórios
- Em núcleos irmãos SMP do mesmo pacote, pode ser observado um machine check
- Se dois núcleos diferentes não forem especificados, pode ser necessária uma hammer thread
Possível causa e impactos observados
- Como o comportamento do microcódigo em sistemas modernos não é público, a causa raiz só pode ser tratada como uma teoria baseada em observações
- A CPU se divide, em termos gerais, em front-end e back-end
- O front-end busca e decodifica instruções, gerando μops
- O back-end executa instruções fora de ordem e armazena e finaliza os resultados no ROB (reorder buffer)
- Este bug parece fazer o front-end calcular incorretamente o tamanho da instrução
movsb, levando a um estado em que entradas posteriores do ROB são associadas a endereços incorretos - Nesse estado, ocorre uma confusão em que o ponteiro de instrução é calculado de forma errada
- O sistema pode acabar se recuperando internamente para um estado consistente, mas resultados intermediários podem estar incorretos
- Se vários núcleos SMT ou SMP entram nesse estado simultaneamente, pode ocorrer dano suficiente ao estado microarquitetural para forçar um machine check
- É possível corromper o estado do sistema a ponto de provocar um machine check, e foi observada interferência entre threads na execução de processos agendados em núcleos irmãos SMT
- Não foi confirmado se a corrupção pode ser controlada com precisão suficiente para escalonamento de privilégios
Mitigações
- A Intel publicou microcódigo atualizado para todos os processadores afetados em INTEL-SA-00950
- O sistema operacional ou o fornecedor do BIOS talvez já tenham disponibilizado a atualização
- Caso não seja possível atualizar, é possível desativar fast strings por meio do registrador específico de modelo
IA32_MISC_ENABLE - Desativar fast strings causa uma grande queda de desempenho, portanto não deve ser usado a menos que seja realmente necessário
Materiais relacionados sobre bugs de CPU
- O Google vem divulgando bugs de CPU que encontrou, e alguns valem a leitura mesmo quando não têm impacto de segurança
- Exemplos de materiais:
- movlps just doesn’t work: caso em que
movlpsnão funciona - registers can sometimes roll back: caso em que registradores revertem para um valor anterior
- movlps just doesn’t work: caso em que
1 comentários
Opiniões no Hacker News
Artigo relacionado: https://cloud.google.com/blog/products/identity-security/goo...
Conteúdo vindo de https://news.ycombinator.com/item?id=38268043, mas os comentários foram consolidados aqui
Ao ler este artigo, percebi o quanto sei pouco sobre o hardware em que meu software roda
Ele diz que “prefixos permitem ativar ou desativar funcionalidades para mudar o comportamento das instruções”; fico curioso por que seria necessário um “prefixo” para ligar e desligar funcionalidades
Seria para alternar recursos dinamicamente sem entrar no BIOS?
O prefixo REP é o mais comum e serve para fazer a mesma instrução se repetir um número variável de vezes
A contagem de repetições vem do registrador CX, o que torna muito curtos loops comuns, como mover objetos na memória
A função memcpy muitas vezes é inlineada como uma única instrução REP MOVS, acompanhada, se necessário, de uma instrução que copia a contagem para CX
O prefixo REX também é bastante comum, porque programas de 64 bits lidam frequentemente com valores e endereços de 64 bits
Nenhum prefixo alterna algo configurável globalmente via BIOS ou afins; todos apenas especificam o que a próxima instrução deve fazer
Modos de endereçamento raramente usados levam um “prefixo de segmento” que faz usar um segmento diferente de DS, e o prefixo “REX” do x86_64 adicionou bits aos campos de registradores para permitir usar 16 registradores de uso geral
Da mesma forma, embora a especificação original fosse ruim, o prefixo “LOCK” torna algumas operações de memória atômicas em relação ao restante do sistema, como ao implementar compare-and-set com “LOCK CMPXCHG”
Outras arquiteturas de CPU também expressam essas operações, mas geralmente as colocam dentro do espaço de instruções existente, o que exige mais bits para representar todas as instruções
O prefixo “REP” que está em questão aqui é uma espécie de exceção: é um prefixo de repetição em microcódigo que sobrou dos tempos antigos
Ainda assim, ele representa operações sensíveis a desempenho até hoje, como memset/memmove, então vale a pena para fabricantes de CPU continuarem otimizando isso, e este bug parece ter surgido nesse processo
O maior problema é que ele “usou de forma eficiente” o espaço de codificação das instruções
Quando depois surgiram novas instruções e, pior, registradores adicionais, foi preciso encaixar de algum jeito novas variantes de instruções, e a solução foi acrescentar prefixos
A cada expansão do conjunto de instruções, escavaram uma parte do espaço de opcodes para enfiar um novo prefixo
Pelo fato de a Intel ter proposto ainda outro método novo este ano, parece que essa tendência vai continuar
O processo de diagnóstico me lembrou do que aconteceu quando o qemu encontrou repz ret: https://repzret.org/p/repzret/
Acho que, pelas regras do HN, títulos assim deveriam ser proibidos
Ele não diz absolutamente nada sobre o que é o link, e a URL só confunde ainda mais
Se o título é tão sem sentido, acho que quem postou deveria acrescentar uma breve explicação
Já vi que, quando o título traz o máximo de contexto possível, as pessoas não clicam no link e passam a polir nos comentários apenas seus próprios interesses, como se estivessem reagindo a um tweet
O HN escolhe um meio-termo que incentiva a curiosidade intelectual e o clique no link
Mesmo que alguém se recuse a clicar por causa de um título ambíguo, pelo menos vai responder às pessoas que clicaram, o que considero melhor do que em outros lugares da internet
Posts sem recompensa suficiente para justificar um título ambíguo e espirituoso, ao contrário deste, saem da primeira página
O texto é muito bem escrito
Quase não entendo de programação em assembly, nem do conjunto de instruções da Intel, e muito menos de microarquitetura, mas consegui acompanhar a explicação e sinto que entendi em linhas gerais o que está acontecendo aqui
Fico curioso se alguém sabe se CPUs da AMD também são afetadas
Se o problema é realmente o processador se confundir com o comprimento da instrução, é impressionante que isso possa ser corrigido em microcódigo sem uma grande perda de desempenho
Meu instinto pode estar completamente errado, mas eu imaginaria que o cálculo do comprimento da instrução fosse algo sintetizado diretamente em portas lógicas
Pensando de novo, talvez o decodificador de uOPs esteja perfeitamente correto em hardware, e uma rotina de cópia otimizada em microcódigo esteja tentando inferir algo falso sobre o fluxo de uOPs
Por exemplo, algo como “ah, isto é rep mov, então basta voltar duas uOPs para fazer o loop”
Imagino que a equipe de CPUs da Intel não vá divulgar detalhes tão específicos
Não conheço bem “ERMS” e “FSRM”, e quase não parece haver bons materiais no Google
Fico me perguntando se eles são apenas flags CPUID que indicam que rep movsb pode ser usado com desempenho máximo em vez de uma implementação SSE otimizada de memcpy, ou se são alguma codificação ou prefixo especial que torna rep movsb mais rápido
Se for o segundo caso, não sei por que seriam necessários nem como fsrm é utilizado
ERMS parece ter sido uma alternativa mais barata ao AVX, e FSRM, uma versão melhor para blocos curtos
“As versões de baixo custo de processadores posteriores, os Kaby Lake Celeron e Pentium lançados em 2017, não têm AVX, que pode ser usado para cópia rápida de memória, mas têm Enhanced REP MOVSB
E algumas arquiteturas móveis e de baixo consumo da Intel lançadas a partir de 2018 não eram baseadas em SkyLake, mas copiavam cerca de duas vezes mais bytes por ciclo de CPU com REP MOVSB do que as microarquiteturas da geração anterior”
“Antes do Fast Short REP MOV(FSRM) da microarquitetura Ice Lake, o Enhanced REP MOVSB(ERMSB) só era mais rápido que cópias AVX ou cópias com registradores de uso geral quando o tamanho do bloco era de pelo menos 256 bytes
Em blocos menores que 64 bytes, o custo interno de inicialização do ERMSB era alto, cerca de 35 ciclos, tornando-o muito mais lento; o objetivo do recurso FSRM era tornar também rápidos os blocos menores que 128 bytes”
[1] https://stackoverflow.com/a/43837564
[2] http://www.intel.com/content/dam/www/public/us/en/documents/...
A escolha e o escalonamento ideais de instruções podem ser feitos estaticamente em tempo de compilação, ou dinamicamente em tempo de execução, escolhendo uma entre várias funções de biblioteca ou usando JIT
Para detectar em tempo de execução qual escalonamento de instruções é o ideal, é preciso conhecer a CPU real
Seria possível manter uma tabela com todos os modelos de CPU, mas também é possível perguntar ao sistema operacional se a CPU em execução implementa aquela otimização
O Linux precisou de um patch para permitir informar que a CPU implementava essa otimização
https://www.phoronix.com/news/Intel-5.6-FSRM-Memmove
Vi que o comunicado da Intel [1] dizia o seguinte
A Intel agradeceu aos funcionários da Intel que descobriram internamente esse problema, e também agradeceu aos funcionários do Google que relataram o problema
[1] https://www.intel.com/content/www/us/en/security-center/advi...
O comunicado da Intel com a descrição do impacto também merece referência: https://www.intel.com/content/www/us/en/security-center/advi...
“Em alguns processadores Intel(R), uma sequência de instruções do processador pode causar comportamento inesperado, permitindo que um usuário autenticado, por meio de acesso local, possibilite elevação de privilégio, divulgação de informações ou negação de serviço”
Konrad Magnusson, da equipe de Victoria 3 da Paradox Interactive, encontrou algo relacionado a isso e ao mimalloc: https://github.com/microsoft/mimalloc/issues/807
Não sei se é totalmente relacionado, mas é possível