A implementação do mecanismo KFence (Kernel Electric Fence), que verifica o uso de memória, detectando acessos fora dos limites dos buffers, acessos à memória após a liberação e outros erros semelhantes, está incluída no desenvolvimento do núcleo Linux 5.12.
Funcionalidade semelhante já existia no núcleo sob a forma da opção de compilação KASAN (kernel address sanitizer, que usa o Address Sanitizer em versões modernas do gcc e clang) — no entanto, era principalmente posicionada para uso de depuração. O subsistema KFence se distingue do KASAN pela alta velocidade de operação, permitindo usar essa capacidade até mesmo em núcleos de sistemas em produção.
A aplicação em sistemas em produção permitirá detectar erros de uso da memória que não aparecem em execuções de teste e surgem apenas sob cargas de trabalho ou após longos períodos de operação (para longos uptimes). Além disso, usar o KFence em sistemas em produção permitirá aumentar significativamente o número de máquinas envolvidas na verificação da operação do núcleo com a memória.
A mínima sobrecarga, independente da carga de trabalho, é alcançada no KFence pela inserção de páginas de proteção (guard pages) na heap em intervalos fixos. Após o término do tempo de cada intervalo de proteção, o KFence, através do sistema de alocação de memória padrão (SLAB ou SLUB allocator), adiciona mais uma página de proteção do pool de objetos KFence e reinicia a contagem do temporizador. Cada objeto KFence é alocado em uma página de memória separada, e as páginas de memória nas bordas esquerda e direita formam as páginas de proteção (guard pages), cujo tamanho é escolhido aleatoriamente.
Assim, as páginas com objetos são separadas umas das outras por páginas de proteção, que são configuradas para gerar um "page fault" em qualquer acesso. Para identificar operações de gravação fora dos limites do buffer dentro das páginas com objetos, são usadas "zonas vermelhas" baseadas em padrões, que ocupam a memória não utilizada pelos objetos, permanecendo durante o alinhamento do tamanho das páginas de memória. —+————+————+————+————+————+— | xxxxxxxxx | O : | xxxxxxxxx | : O | xxxxxxxxx | | xxxxxxxxx | B : | xxxxxxxxx | : B | xxxxxxxxx | | x GUARD x | J : RED- | x GUARD x | RED- : J | x GUARD x | | xxxxxxxxx | E : ZONE | xxxxxxxxx | ZONE : E | xxxxxxxxx | | xxxxxxxxx | C : | xxxxxxxxx | : C | xxxxxxxxx | | xxxxxxxxx | T : | xxxxxxxxx | : T | xxxxxxxxx | —+————+————+————+————+————+—
No caso de uma tentativa de acessar uma área fora dos limites do buffer, a operação afeta a página de proteção, o que resulta na geração de um "page fault", que é interceptado pelo KFence e registra os dados do problema identificado. Por padrão, o KFence não bloqueia o erro e apenas gera um aviso no log, mas há uma configuração "panic_on_warn", que permite, em caso de erro, levar o núcleo a um estado de falha (panic).
Fonte: opennet.ru
