O KFENCE (Kernel Electric-Fence) é uma ferramenta de baixo overhead para o kernel Linux que detecta corrupção de memória no código e nos módulos do kernel e gera relatórios de erro detalhados.
O Alibaba Cloud Linux 3 aprimora o KFENCE com ativação e desativação dinâmicas, monitoramento por slab e dimensionamento de pool baseado em memória, adequando-o tanto para ambientes de produção quanto para uso offline.
Quando usar o KFENCE
O KFENCE troca memória por um impacto mínimo na CPU e oferece suporte a dois casos de uso:
Monitoramento de produção: ative o modo de amostragem em todo o seu parque. Com tempo de atividade suficiente, o KFENCE captura bugs em caminhos de código raramente exercitados por cargas de trabalho de teste. O consumo chega a 2 MiB com impacto de desempenho insignificante.
Depuração offline: ative o modo completo para monitorar todas as alocações de um tipo específico de slab. Consome memória na ordem de GiB, mas captura todas as alocações dentro do escopo definido. Ideal para reproduzir problemas conhecidos.
Desenvolvedores de kernel e módulos podem usar o KFENCE para detectar corrupção de memória em seus códigos. Usuários que enfrentam falhas podem ativar o KFENCE para coletar dados de crash destinados aos desenvolvedores da Alibaba Cloud ou de drivers de terceiros.
Pré-requisitos
O KFENCE requer o Alibaba Cloud Linux 3 com as seguintes versões mínimas de kernel:
|
Arquitetura |
Versão mínima do kernel |
|
x86 |
|
|
Arm |
|
KFENCE vs. Kernel Address Sanitizer (KASAN)
Ambos são detectores de corrupção de memória integrados ao kernel Linux. A Alibaba Cloud aprimorou o KFENCE no kernel 5.10.
|
Dimensão |
KFENCE |
KASAN |
|
Escopo de monitoramento |
Slabs de até 4 KiB (por exemplo, |
Todos os tipos de slab, memória de página, memória de pilha e memória global |
|
Taxa de detecção |
Maior taxa de sucesso dentro do intervalo de monitoramento |
-- |
|
Overhead de memória |
Maior |
Menor |
|
Impacto no desempenho |
Menor (adequado para produção) |
Maior (geralmente usado em ambientes de teste) |
Não ative o KFENCE e o KASAN simultaneamente. O KFENCE assume os objetos de monitoramento do KASAN.
Conceitos principais
|
Termo |
Descrição |
|
Poluição de memória |
Modificação ou corrupção não intencional da memória durante a execução do programa, causando exceções ou falhas. Causas comuns incluem erros de programação, vulnerabilidades de software, malware e falhas de hardware. |
|
Slab |
Mecanismo de alocação de memória do kernel que pré-aloca objetos em um pool de cache para alocação e liberação rápidas, reduzindo o overhead de operações frequentes de memória. |
|
Página order-0 |
Um quadro de página de 4 KiB — a menor unidade de alocação de memória no kernel Linux. |
Ativar o KFENCE
Monitoramento de produção
Detecte corrupção de memória em um ambiente ativo com overhead mínimo.
Cenário 1: Modo de amostragem via parâmetros de boot
O KFENCE amostra alocações de memória em um intervalo fixo. O consumo de memória chega a 2 MiB sem impacto mensurável no desempenho.
-
Adicione o parâmetro de boot
kfence.sample_interval. Substitua<sample-interval>pelo intervalo de amostragem em milissegundos. Por exemplo,100= a cada 100 ms.sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.sample_interval=<sample-interval>" -
(Opcional) Adicione o parâmetro
kfence.booting_maxpara limitar a memória do KFENCE com base na memória total do sistema. Substitua<booting-max>por uma string de notação de segmento como0-128M:0,128M-256M:1M,256M-:2M.sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.booting_max=<booting-max>" Reinicie o sistema operacional para aplicar a configuração. Restart an instance.
Cenário 2: Modo completo para slabs específicos via script
Este modo monitora todas as alocações para os tipos de slab especificados. O consumo de memória é da ordem de GiB. Use com cautela em máquinas com memória limitada.
-
Crie um script chamado
kfence.sh. O script conta objetos de slab ativos, dimensiona o pool, desativa o monitoramento para outros slabs e páginas order-0 e, em seguida, ativa o monitoramento em modo completo para os slabs especificados.NotaO KFENCE monitora tanto slabs quanto páginas order-0. Slabs são o mecanismo de alocação otimizada do kernel para objetos frequentemente utilizados.
#!/bin/bash # usage: ./kfence.sh kmalloc-64 SLAB_PREFIX=/sys/kernel/slab MODULE_PREFIX=/sys/module/kfence/parameters if [ $# -eq 0 ]; then echo "err: please input slabs" exit 1 fi #check whether slab exists for i in $@; do slab_path=$SLAB_PREFIX/$i if [ ! -d $slab_path ]; then echo "err: slab $i not exist!" exit 1 fi done #calculate num_objects sumobj=0 for i in $@; do objects=($(cat $SLAB_PREFIX/$i/objects)) maxobj=1 for ((j=1; j<${#objects[@]}; j++)); do nodeobj=$(echo ${objects[$j]} | awk -F= '{print $2}') [ $maxobj -lt $nodeobj ] && maxobj=$nodeobj done ((sumobj += maxobj)) done echo "recommend num_objects per node: $sumobj" #check kfence stats if [ $(cat $MODULE_PREFIX/sample_interval) -ne 0 ]; then echo "kfence is running, disable it and wait..." echo 0 > $MODULE_PREFIX/sample_interval sleep 1 fi #disable all slabs catching for file in $SLAB_PREFIX/* do (echo 0 > $file/kfence_enable) 2>/dev/null || echo 1 > $file/skip_kfence done #disable order0 page catching echo 0 > $MODULE_PREFIX/order0_page #enable setting slabs catching for i in $@; do (echo 1 > $SLAB_PREFIX/$i/kfence_enable) 2>/dev/null || echo 0 > $SLAB_PREFIX/$i/skip_kfence done #setting num_objects and node mode echo $sumobj > $MODULE_PREFIX/num_objects echo node > $MODULE_PREFIX/pool_mode #start kfence echo -1 > $MODULE_PREFIX/sample_interval if [ $? -ne 0 ]; then echo "err: kfence enable fail!" exit 1 fi echo "kfence enabled!" -
Execute o script com o tipo de slab a ser monitorado:
sudo bash ./kfence.sh kmalloc-64
Depuração offline
Capture todas as alocações de memória dentro de um escopo amplo. Alto consumo de memória, cobertura máxima de detecção.
Parâmetros de boot (x86)
-
Adicione os seguintes parâmetros de boot.
Parâmetro
Valor neste exemplo
Efeito
num_objects1000000O pool pode monitorar até 1.000.000 objetos slab, consumindo até ceil(1.000.000 / 131.071) = 8 GiB. Defina como aproximadamente 10% da memória disponível.
sample_interval-1Modo completo: monitora toda a memória correspondente ao escopo configurado.
faultpanicDispara um kernel panic quando um problema é detectado, preservando o core dump para análise.
sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.num_objects=1000000" sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.sample_interval=-1" sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="kfence.fault=panic" Reinicie o sistema operacional. Restart an instance.
Parâmetros de runtime (x86 ou Arm)
O KFENCE ativado em runtime não detecta corrupção de memória durante a inicialização do kernel.
Para alterar
num_objectsousample_intervalapós ativar o KFENCE, primeiro desative-o. As alterações emnum_objectsentram em vigor na próxima vez que o KFENCE for ativado.
Execute os seguintes comandos.
sudo sh -c 'echo 1000000 > /sys/module/kfence/parameters/num_objects'
sudo sh -c 'echo -1 > /sys/module/kfence/parameters/sample_interval'
sudo sh -c 'echo panic > /sys/module/kfence/parameters/fault'
Os parâmetros assumem os mesmos valores descritos na seção Parâmetros de boot (x86) acima.
Se a versão do seu kernel for anterior à 5.10.134-16, o parâmetro fault não estará disponível. Ignore com segurança a mensagem de erro exibida ao gravar nele.
Verificar resultados
Após ativar o KFENCE, verifique se há problemas detectados.
Visualize estatísticas de detecção
sudo cat /sys/kernel/debug/kfence/stats
Se houver problemas detectados, a contagem de total bugs será maior que zero.
Visualize detalhes do erro
dmesg | grep -i kfence
Filtra mensagens do kernel em busca de relatórios de erro do KFENCE.
Desativar o KFENCE
O KFENCE é um componente padrão integrado à imagem do kernel do Alibaba Cloud Linux (configuração do kernel CONFIG_KFENCE=y). Não é possível desativá-lo por meio de patch de kernel (kpatch), atualização quente ou pacote de software. Use o seguinte comando manual para desativá-lo.
-
Interrompa o monitoramento do KFENCE. O KFENCE para de monitorar novas alocações. Assim que toda a memória monitorada no pool for liberada, o KFENCE a devolve ao sistema buddy do kernel em incrementos de 1 GiB.
sudo bash -c 'echo 0 > /sys/module/kfence/parameters/sample_interval' -
(Opcional) Se o KFENCE foi ativado via parâmetros de boot, remova-os para impedir que o KFENCE inicie na próxima inicialização:
sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --remove-args="kfence.sample_interval"
Referência de parâmetros
Configure o KFENCE por meio de argumentos de boot ou em runtime via /sys/module/kfence/parameters/.
|
Parâmetro |
Descrição |
Valores válidos |
Padrão |
|
|
Intervalo de amostragem para monitoramento de memória. |
|
-- |
|
|
Número máximo de objetos slab que o pool do KFENCE pode monitorar. Determina o tamanho do pool e o consumo de memória. |
Inteiro positivo. Defina como aproximadamente 10% da memória máxima disponível para depuração offline. |
|
|
|
Ação executada quando corrupção de memória é detectada. Disponível no kernel |
|
|
|
|
Limite de memória para o KFENCE com base na memória total do sistema. Disponível no kernel |
Notação de segmento, ex.: |
|
|
|
Ativa ou desativa o monitoramento de páginas order-0. |
|
-- |
|
|
Estratégia de alocação do pool. |
|
-- |
Fórmulas de consumo de memória
O consumo máximo de memória depende de num_objects:
Quando
num_objectsé menor ou igual a 131.071: (num_objects + 1) x 8 KiBQuando
num_objectsé maior que 131.071: ceil(num_objects / 131.071) GiB
Por exemplo, definir num_objects como 1.000.000 resulta em um consumo máximo de ceil(1.000.000 / 131.071) = 8 GiB.
O parâmetro booting_max
O parâmetro kfence.booting_max limita a memória do KFENCE com base na memória total do sistema. Cada segmento mapeia um intervalo de memória para um limite do KFENCE.
Configuração padrão (kernel 5.10.134-17 ou posterior):
kfence.booting_max=0-2G:0,2G-32G:2M,32G-:32M
|
Segmento |
Significado |
|
|
Memória total abaixo de 2 GiB: KFENCE está desativado |
|
|
Memória total entre 2 GiB e 32 GiB: KFENCE pode consumir até 2 MiB |
|
|
Memória total acima de 32 GiB: KFENCE pode consumir até 32 MiB |
Com o valor padrão de num_objects de 255, o overhead de memória do KFENCE permanece abaixo de 1 por mil da memória total. Com páginas padrão de 4 KiB, o consumo máximo é de 2 MiB. Com huge pages de 64 KiB, é de 32 MiB.
O parâmetro booting_max restringe num_objects apenas no momento do boot. O consumo real de memória pode ser inferior ao limite. Este parâmetro não se aplica quando o KFENCE é ativado em runtime.
Exemplo personalizado: 0-128M:0,128M-256M:1M,256M-:2M
|
Segmento |
Significado |
|
|
Memória total abaixo de 128 MiB: KFENCE está desativado |
|
|
Memória total entre 128 MiB e 256 MiB: KFENCE pode consumir até 1 MiB ( |
|
|
Memória total acima de 256 MiB: KFENCE pode consumir até 2 MiB ( |