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 em tempo de compilação pelo número de syscalls registrados. Isso significa que não há espaço para outro.
Você pode verificar a implementação, por exemplo, da arquitetura x86 no arquivo arch/x86/kernel/syscall_64.c
, onde sys_call_table
está definido. Seu tamanho é exatamente __NR_syscall_max+1
. __NR_syscall_max
é definido em arch/x86/kernel/asm-offsets_64.c
como sizeof(syscalls) - 1
(é o número do último syscall), em que syscall
é uma tabela com todos os syscalls.
Uma solução possível é reutilizar alguns existentes (ou preteridos, se a arquitetura tiver um, veja sys_setaltroot
, por exemplo), o número syscall com 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ê possa usar isso também.
Você pode usar esta técnica se estiver desenvolvendo o novo syscall e quiser apenas evitar a reinicialização enquanto estiver experimentando. Você terá que definir sua nova chamada de sistema, encontrar a entrada existente na tabela syscall e então substituí-la de 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 os módulos a partir da versão 2.6 (a última versão do kernel que tinha este símbolo exportado era 2.5.41
).
Uma maneira de contornar isso é alterar o kernel para exportar o símbolo sys_call_table
para módulos. Para fazer isso, você precisa adicionar duas linhas a kernel/kallsyms.c
( não faça isso em máquinas de produção ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
Outra técnica é encontrar a tabela syscall dinamicamente. Você itera a memória do kernel, comparando cada palavra com um ponteiro para a função de chamada do sistema conhecida. Desde que você conhece o deslocamento deste conhecimento na tabela, você pode calcular o endereço inicial da tabela.