Módulo de kernel carregável - Loadable kernel module

Na computação , um módulo de kernel carregável ( LKM ) é um arquivo de objeto que contém código para estender o kernel em execução , ou o chamado kernel base , de um sistema operacional . LKMs são normalmente usados ​​para adicionar suporte para novo hardware (como drivers de dispositivo ) e / ou sistemas de arquivos , ou para adicionar chamadas de sistema . Quando a funcionalidade fornecida por um LKM não é mais necessária, ele pode ser descarregado para liberar memória e outros recursos.

A maioria dos sistemas atuais do tipo Unix e Microsoft Windows suportam módulos de kernel carregáveis ​​com nomes diferentes, como módulo de kernel carregável ( kld ) no FreeBSD , extensão de kernel ( kext ) no macOS (agora obsoleto), módulo de extensão de kernel no AIX , driver do modo kernel no Windows NT e módulo do kernel para download ( DKM ) no VxWorks . Eles também são conhecidos como módulos carregáveis ​​do kernel (ou KLM ) e simplesmente como módulos do kernel ( KMOD ).

Vantagens

Sem módulos de kernel carregáveis, um sistema operacional teria que incluir todas as funcionalidades antecipadas possíveis compiladas diretamente no kernel base. Grande parte dessa funcionalidade residiria na memória sem ser usada, desperdiçando memória, e exigiria que os usuários reconstruíssem e reinicializassem o kernel base sempre que precisassem de uma nova funcionalidade.

Desvantagens

Uma crítica menor de preferir um kernel modular a um kernel estático é a chamada penalidade de fragmentação . O kernel básico é sempre desempacotado na memória contígua real por suas rotinas de configuração; portanto, o código base do kernel nunca é fragmentado. Uma vez que o sistema está em um estado no qual os módulos podem ser inseridos, por exemplo, uma vez que os sistemas de arquivos que contêm os módulos tenham sido montados , é provável que qualquer nova inserção de código de kernel fará com que o kernel fique fragmentado, introduzindo assim uma pequena penalidade de desempenho usando mais entradas de TLB , causando mais erros de TLB.

Implementações em diferentes sistemas operacionais

Linux

Módulos de kernel carregáveis ​​no Linux são carregados (e descarregados) pelo comando modprobe . Eles estão localizados em / lib / modules ou / usr / lib / modules e têm a extensão .ko ("objeto do kernel") desde a versão 2.6 (versões anteriores usavam a extensão .o ). O comando lsmod lista os módulos do kernel carregados. Em casos de emergência, quando o sistema falha ao inicializar devido a, por exemplo, módulos quebrados, módulos específicos podem ser habilitados ou desabilitados modificando a lista de parâmetros de inicialização do kernel (por exemplo, se estiver usando GRUB , pressionando 'e' no menu Iniciar GRUB, editar a linha de parâmetro do kernel).

Problemas de licença

Na opinião dos mantenedores do Linux, LKM são trabalhos derivados do kernel. Os mantenedores do Linux toleram a distribuição de módulos proprietários , mas permitem que os símbolos sejam marcados como disponíveis apenas para módulos GNU General Public License (GPL).

Carregar um módulo proprietário ou não compatível com a GPL definirá um sinalizador 'contaminado' no kernel em execução - o que significa que quaisquer problemas ou bugs experimentados serão menos prováveis ​​de serem investigados pelos mantenedores. Os LKMs tornam-se efetivamente parte do kernel em execução, portanto, podem corromper as estruturas de dados do kernel e produzir bugs que podem não ser investigados se o módulo for realmente proprietário.

Controvérsia Linuxant

Em 2004, a Linuxant, uma empresa de consultoria que lança drivers de dispositivos proprietários como módulos de kernel carregáveis, tentou abusar de um terminador nulo em seus MODULE_LICENSE, conforme visível no seguinte trecho de código:

MODULE_LICENSE("GPL\0for files in the \"GPL\" directory; for others, only LICENSE file applies");

O código de comparação de strings usado pelo kernel na época tentou determinar se o módulo foi interrompido por GPL quando atingiu um caractere nulo ( \ 0 ), então foi enganado ao pensar que o módulo estava declarando sua licença apenas "GPL" .

FreeBSD

Módulos de kernel para FreeBSD são armazenados em / boot / kernel / para módulos distribuídos com o sistema operacional , ou geralmente / boot / modules / para módulos instalados a partir de portas do FreeBSD ou pacotes do FreeBSD , ou para módulos proprietários ou apenas binários. Os módulos do kernel do FreeBSD geralmente têm a extensão .ko . Assim que a máquina for inicializada, eles podem ser carregados com o comando kldload , descarregados com kldunload e listados com kldstat . Os módulos também podem ser carregados do carregador antes do kernel iniciar, automaticamente (por meio de /boot/loader.conf ) ou manualmente.

Mac OS

Alguns módulos de kernel carregáveis ​​no macOS podem ser carregados automaticamente. Módulos de kernel carregáveis ​​também podem ser carregados pelo comando kextload . Eles podem ser listados pelo comando kextstat . Módulos de kernel carregáveis ​​estão localizados em pacotes com a extensão .kext . Os módulos fornecidos com o sistema operacional são armazenados no diretório / System / Library / Extensions ; módulos fornecidos por terceiros estão em vários outros diretórios.

NetWare

Um módulo de kernel NetWare é conhecido como NetWare Loadable Module (NLM). Os NLMs são inseridos no kernel do NetWare por meio do comando LOAD e removidos por meio do comando UNLOAD; o comando modules lista os módulos do kernel carregados atualmente. Os NLMs podem residir em qualquer caminho de pesquisa válido atribuído no servidor NetWare e têm .NLM como a extensão do nome do arquivo.

VxWorks

Um projeto do tipo módulo do kernel para download (DKM) pode ser criado para gerar um arquivo ".out" que pode então ser carregado no espaço do kernel usando o comando "ld". Este módulo de kernel para download pode ser descarregado usando o comando "unld".

Solaris

Solaris tem um caminho de carregamento de módulo de kernel configurável, o padrão é / platform / platform-name / kernel / kernel / usr / kernel . A maioria dos módulos do kernel estão em subdiretórios em / kernel ; aqueles que não são considerados necessários para inicializar o sistema até o ponto em que o init pode iniciar são freqüentemente (mas nem sempre) encontrados em / usr / kernel . Ao executar um kernel DEBUG, o sistema tenta ativamente descarregar os módulos.

Compatibilidade binária

O Linux não fornece uma API ou ABI estável para módulos do kernel. Isso significa que existem diferenças na estrutura interna e na função entre as diferentes versões do kernel, o que pode causar problemas de compatibilidade. Em uma tentativa de combater esses problemas, os dados de versão de símbolo são colocados dentro da seção .modinfo dos módulos ELF carregáveis . Essas informações de versão podem ser comparadas com as do kernel em execução antes de carregar um módulo; se as versões forem incompatíveis, o módulo não será carregado.

Outros sistemas operacionais, como Solaris , FreeBSD , macOS e Windows mantêm a API e a ABI do kernel relativamente estáveis, evitando assim este problema. Por exemplo, os módulos do kernel do FreeBSD compilados na versão 6.0 do kernel funcionarão sem recompilação em qualquer outra versão 6.x do FreeBSD, por exemplo, 6.4. No entanto, eles não são compatíveis com outras versões principais e devem ser recompilados para uso com o FreeBSD 7.x, já que a compatibilidade API e ABI é mantida apenas dentro de um branch.

Segurança

Embora os módulos carregáveis ​​do kernel sejam um método conveniente de modificar o kernel em execução, isso pode ser abusado por invasores em um sistema comprometido para evitar a detecção de seus processos ou arquivos , permitindo-lhes manter o controle sobre o sistema. Muitos rootkits usam LKMs dessa maneira. Observe que, na maioria dos sistemas operacionais, os módulos não ajudam na elevação de privilégios , pois privilégios elevados são necessários para carregar um LKM; eles simplesmente tornam mais fácil para o invasor ocultar a invasão.

Linux

O Linux permite desabilitar o carregamento do módulo por meio da opção sysctl/proc/sys/kernel/modules_disabled . Um sistema initramfs pode carregar módulos específicos necessários para uma máquina na inicialização e então desabilitar o carregamento do módulo. Isso torna a segurança muito semelhante a um kernel monolítico. Se um invasor puder alterar o initramfs, ele poderá alterar o binário do kernel.

Mac OS

No OS X Yosemite e em versões posteriores, uma extensão do kernel deve ser assinada por código com um certificado de desenvolvedor que detém um "direito" específico para isso. Esse certificado de desenvolvedor é fornecido pela Apple apenas mediante solicitação e não é fornecido automaticamente aos membros desenvolvedores da Apple . Este recurso, chamado "assinatura kext", é habilitado por padrão e instrui o kernel a parar de inicializar se extensões de kernel não assinadas estiverem presentes. No OS X El Capitan e versões posteriores, é parte da Proteção de Integridade do Sistema .

Em versões anteriores do macOS, ou se a assinatura kext estiver desabilitada, um módulo de kernel carregável em um pacote de extensão de kernel pode ser carregado por usuários não root se a propriedade OSBundleAllowUserLoad estiver definida como True na lista de propriedades do pacote. No entanto, se qualquer um dos arquivos no pacote, incluindo o arquivo de código executável, não pertencer ao root e ao group wheel, ou for gravável pelo grupo ou "outro", a tentativa de carregar o módulo carregável do kernel falhará.

Solaris

Módulos de kernel podem opcionalmente ter uma seção ELF de assinatura criptográfica que é verificada no carregamento, dependendo das configurações da política de inicialização verificada. O kernel pode garantir que os módulos sejam assinados criptograficamente por um conjunto de certificados confiáveis; a lista de certificados confiáveis ​​é mantida fora do sistema operacional no ILOM em algumas plataformas baseadas em SPARC. O carregamento do módulo do kernel iniciado no espaço do usuário só é possível a partir do caminho confiável quando o sistema está sendo executado com o recurso Immutable Global Zone habilitado.

Veja também

Referências