Adicionando uma nova chamada do sistema ao Linux 3.2.x com um módulo carregável do kernel [fechado]

11

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?

abhi
fonte
Esta questão está fora de tópico aqui: Unix e Linux são sobre uso e administração, não sobre programação. Você deve perguntar no Stack Overflow . Não seja tão vago: crie um link para as postagens encontradas no Stack Overflow e explique o que achou inconclusivo ou contraditório.
Gilles 'SO- stop be evil'
2
Acredito que esta questão esteja muito mais relacionada ao Linux como sistema operacional do que à própria programação. Também é muito importante saber quais são as possibilidades de ampliar as habilidades do sistema e quais são seus limites. Isso, por exemplo, faz você entender por que alguns recursos não são possíveis de serem implementados como módulo carregável e precisam de correção do kernel. Saber por que é assim também pode lhe dar algumas idéias de segurança versus usabilidade que os desenvolvedores do kernel precisam fazer. Essa pergunta seria mais detalhada se o OP perguntasse apenas se é possível e por que não e não como implementá-lo?
Krzysztof Adamski
1
Houve inúmeras discussões sobre <stroke> flames </stroke> na lista de discussão do Linux Kernel, por exemplo, o reiserfs usou seus próprios syscalls, que não eram realmente amados por alguns desenvolvedores principais, incluindo Linus. No seu caso, eu simplesmente usaria 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.
peterh - Restabelece Monica

Respostas:

14

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.carquivo, onde sys_call_tableestá definido. Seu tamanho é exatamente __NR_syscall_max+1. __NR_syscall_maxé definido arch/x86/kernel/asm-offsets_64.ccomo sizeof(syscalls) - 1(é o número do último syscall), onde syscallé uma tabela com todos os syscalls.

Uma solução possível é reutilizar um sys_setaltrootnú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_tablepara módulos a partir da versão 2.6 (a última versão do kernel que teve esse símbolo exportado foi 2.5.41).

Uma maneira de contornar isso é mudar o seu kernel para exportar o sys_call_tablesímbolo para os módulos. Para fazer isso, você deve adicionar as duas linhas a seguir kernel/kallsyms.c( não faça isso nas 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 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.

Krzysztof Adamski
fonte
1

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.

PaulDaviesC
fonte