Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

05 - Módulos do Kernel

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

O conceito de LKM (Loadable Kernel Module) é a pedra angular da arquitetura modular do Linux. Ao contrário de sistemas operacionais onde a funcionalidade do núcleo é estática (exigindo recompilação ou reinicialização para suportar um novo hardware), o Linux permite que o código do Ring 0 seja injetado, vinculado e executado sob demanda no espaço de endereçamento do kernel em tempo de execução.

Esta pasta detalha o ciclo de vida desses módulos, as interfaces de comunicação com o espaço do usuário, a resolução de símbolos (a complexa "tabela de endereços" interna do núcleo) e as camadas de configuração que governam o comportamento dinâmico do subsistema de carregamento. O entendimento do carregamento de módulos é, na prática, a compreensão de como o kernel estende suas próprias capacidades para abranger desde sistemas embarcados minimalistas até mainframes de altíssima performance.

01 - Carregamento e Remoção (insmod, rmmod, modprobe)

O processo de extensão do kernel através de módulos é mediado por um conjunto de utilitários de espaço de usuário que interagem diretamente com a syscall init_module() e delete_module(). Embora a função seja similar, a filosofia operacional entre as ferramentas varia drasticamente, sendo fundamental distinguir o carregamento manual bruto do carregamento inteligente baseado em políticas.

insmod: O Carregador Primitivo

O insmod (insert module) é a ferramenta de baixo nível. Ao ser invocado, ele lê um arquivo binário do módulo (um arquivo .ko - Kernel Object, essencialmente um binário ELF realocável) e o passa diretamente para a syscall init_module.

  • Natureza: O insmod não possui conhecimento sobre dependências. Se o módulo A exigir a presença do módulo B (que exporta símbolos dos quais A depende), o insmod falhará se B não estiver carregado.

  • Uso: É reservado quase exclusivamente para depuração e cenários onde o administrador sabe exatamente o caminho completo do módulo e a ordem de dependência.

rmmod: A Remoção Direta

O rmmod invoca a syscall delete_module(). Ele descarrega um módulo específico da memória do kernel.

  • Restrição Arquitetural: O rmmod falhará se o módulo estiver em uso (por exemplo, se um driver de dispositivo ainda estiver vinculado a um hardware, ou se outro módulo depender de seus símbolos exportados). O contador de referência (reference counter) do módulo deve ser obrigatoriamente zero.

modprobe: O Orquestrador Inteligente

O modprobe é o padrão de facto para o gerenciamento de módulos no Linux moderno. Diferente de seus antecessores, ele é consciente do ambiente.

  • Resolução de Dependências: O modprobe consulta um arquivo de banco de dados (modules.dep, gerado pelo depmod), que mapeia as relações entre todos os módulos disponíveis no sistema. Ao solicitar o carregamento do módulo A, o modprobe identifica que B é necessário e carrega B automaticamente antes de A.

  • Carregamento por Alias: O modprobe não exige o caminho completo do arquivo. Ele pode ser invocado pelo nome do módulo, por um alias de hardware (ex: pci:v00008086d00001502) ou pelo nome de uma família de protocolos (ex: net-pf-10 para IPv6). Isso permite que o subsistema de hardware (udev) carregue drivers apenas mencionando o identificador do dispositivo descoberto.

  • Configurabilidade: O modprobe lê os arquivos em /etc/modprobe.d/ para aplicar parâmetros de carregamento (ex: definir o limite de velocidade de uma placa de rede) de forma persistente.

02 - Listagem (lsmod) e Informações (modinfo)

A visibilidade do estado atual do kernel e das capacidades dos binários .ko é provida por ferramentas que leem a memória do kernel e os metadados dos arquivos ELF.

lsmod: O Espelho da Memória do Kernel

O lsmod é um utilitário que não lê o disco, mas sim o arquivo /proc/modules. Este arquivo é gerado dinamicamente pelo kernel e lista todos os módulos carregados. A saída típica do lsmod apresenta:

  • Nome do módulo.

  • Tamanho (em bytes): Indica o espaço de endereçamento que o módulo ocupa na memória do kernel.

  • Contador de referências (Used by): Um campo crítico que exibe quantos outros módulos ou instâncias de hardware estão dependendo deste binário. Se este valor for maior que zero, o módulo é imutável e não pode ser removido pelo rmmod.

modinfo: A Anatomia do Binário .ko

O modinfo é a ferramenta de inspeção estática. Ele analisa a seção .modinfo do binário ELF do módulo (que não é carregado na memória do kernel, poupando RAM). As informações exibidas incluem:

  • filename: O caminho completo no disco.

  • license: A licença do código (ex: "GPL"). Se um módulo não for declarado como GPL, ele é classificado como "Proprietário" e o kernel pode desabilitar o acesso a funções críticas (GPL-only symbols), causando taint (contaminação) no kernel.

  • alias: Os identificadores de hardware que acionam este módulo.

  • parm: Uma lista descritiva dos parâmetros de tempo de carregamento que o módulo aceita (ex: o parâmetro debug=1).

  • depends: A lista de módulos pré-requisitos necessários.

03 - Dependências e Arquivo modules.dep

A complexidade de centenas de módulos interconectados torna o gerenciamento manual das dependências uma tarefa impossível. O kernel Linux delega essa lógica ao utilitário depmod.

O depmod realiza uma varredura profunda no diretório /lib/modules/$(uname -r)/, analisando cada binário .ko. Ele extrai os símbolos exportados (exported symbols) — que são as funções e variáveis C que um módulo disponibiliza para outros — e compara com os símbolos não resolvidos (unresolved symbols) de cada outro módulo.

O Arquivo modules.dep

O resultado desse processamento é o arquivo /lib/modules/$(uname -r)/modules.dep. Este é um arquivo de texto simples onde cada linha contém um módulo seguido pelos módulos dos quais ele depende.

  • Quando o modprobe precisa carregar um módulo, ele não varre o diretório inteiro; ele consulta o modules.dep, resolve o grafo acíclico dirigido das dependências e carrega os módulos na ordem topológica correta.

  • O arquivo modules.dep.bin (uma versão binária indexada) também é gerado para que o acesso do modprobe seja instantâneo, otimizando o boot time do sistema.

04 - Configuração de Módulos (/etc/modprobe.d/)

A necessidade de ajustar comportamentos específicos de um driver (ex: desabilitar suporte a multicast em uma interface, ou ajustar o comportamento de economia de energia de um controlador SATA) sem recompilar o kernel é sanada pelo diretório /etc/modprobe.d/.

Arquivos de configuração nesta pasta são processados automaticamente pelo modprobe sempre que um módulo é carregado. As diretivas mais comuns são:

  1. options <modulo> <parametros>: A diretiva mais poderosa. Permite injetar parâmetros no módulo no momento do carregamento. Exemplo: options i915 enable_fbc=1. Isso força o driver de vídeo Intel a carregar com a compressão de framebuffer habilitada.

  2. blacklist <modulo>: Bloqueia o carregamento automático de um módulo. É a estratégia padrão para impedir que drivers genéricos entrem em conflito com drivers proprietários (ex: colocar blacklist nouveau para permitir a instalação do driver oficial da NVIDIA). O comando modprobe ainda permitirá o carregamento manual, mas o sistema nunca o chamará via alias de hardware.

  3. install <modulo> <comando>: Permite substituir o comportamento padrão de carregamento do módulo. Pode ser usado para executar scripts antes do carregamento real, ou até mesmo para prevenir o carregamento de um driver através de um shell script sofisticado que verifica condições de segurança.

  4. softdep <modulo> pre: <dependencias>: Define dependências "suaves". Ao contrário de dependências fortes exigidas pelo modules.dep, a softdep instrui o modprobe a carregar outros módulos necessários apenas por questões de conveniência ou ordem de inicialização de hardware, mas sem os quais o módulo principal ainda conseguiria operar.

Essa estrutura de configuração permite um controle fino sobre a ABI do kernel, garantindo que o sistema operacional se molde exatamente à topologia física do hardware hospedeiro.