Eu quero adicionar uma nova chamada de sistema específica no kernel do linux 3.2.x, mas como um módulo carregável do kernel (como eu não quero recompilar o kernel repetidamente)
Eu li várias postagens na Internet e também no SO, e alguns lugares afirmam que a implementação de chamadas do sistema como módulos carregáveis não é possível, enquanto outros dizem que é possível.
Qual é? Como é feito se é possível?
ioctl()
s para a tarefa, eles são facilmente modularizáveis. Afaik a principal razão por trás de tornar isso tão difícil quanto possível, que o número de syscalls é uma coisa altamente codificada e ninguém quer o caos como isso entraria em cena. Mas existem inúmeras interfaces do kernel para alcançar a mesma funcionalidade, por exemplo, sysfs, ioctls ou algo assim.Respostas:
Não é possível porque a tabela de chamadas do sistema (chamada
sys_call_table
) é uma matriz de tamanho estático. E seu tamanho é determinado no tempo de compilação pelo número de chamadas de sistema registradas. Isso significa que não há espaço para outro.Você pode verificar a implementação, por exemplo, da arquitetura x86 no
arch/x86/kernel/syscall_64.c
arquivo, ondesys_call_table
está definido. Seu tamanho é exatamente__NR_syscall_max+1
.__NR_syscall_max
é definidoarch/x86/kernel/asm-offsets_64.c
comosizeof(syscalls) - 1
(é o número do último syscall), ondesyscall
é uma tabela com todos os syscalls.Uma solução possível é reutilizar um
sys_setaltroot
número de syscall existente (ou descontinuado, se sua arquitetura tiver um, veja, por exemplo) o seu, pois isso não exigirá mais espaço na memória. Algumas arquiteturas também podem ter buracos na tabela syscall (como a versão de 64 bits do x86) para que você também possa usá-lo.Você pode usar essa técnica se estiver desenvolvendo um novo syscall e apenas desejar evitar a reinicialização durante a experiência. Você precisará definir sua nova chamada do sistema, localizar a entrada existente na tabela syscall e substituí-la do seu módulo.
Fazer isso a partir do módulo do kernel não é trivial, pois o kernel não exporta
sys_call_table
para módulos a partir da versão 2.6 (a última versão do kernel que teve esse símbolo exportado foi2.5.41
).Uma maneira de contornar isso é mudar o seu kernel para exportar o
sys_call_table
símbolo para os módulos. Para fazer isso, você deve adicionar as duas linhas a seguirkernel/kallsyms.c
( não faça isso nas máquinas de produção ):Outra técnica é encontrar a tabela syscall dinamicamente. Você itera na memória do kernel, comparando cada palavra com um ponteiro com a função de chamada do sistema conhecida. Como você conhece o deslocamento desse syscall conhecido na tabela, é possível calcular o endereço inicial da tabela.
fonte
Infelizmente você não pode adicionar chamadas de sistema ao kernel como módulos carregáveis. Você precisa compilar o kernel sempre que adicionar uma nova chamada do sistema.
fonte