/* * adiciona_syscall * * Kernel module que adiciona uma nova chamada de sistema (system call). * * Para compreender melhor este modulo voce precisa ter uma rapida visao * de como funciona system calls no linux. * * No linux as system calls sao chamadas executando a instrucao em assembler * int $0x80, o qual e uma execucao programada (interrupcao de software). * Como o kernel implementa muitas system calls, o processo deve passar * um parametro chamado "system call number" para identificar a system * call desejada. O registrador eax e usado para este proposito. * Assim o kernel usa um numero para identificar cada system call. Em ordem * de associar cada numero com cada system call o kernel usa uma * "system call dispatch table". Esta tabela e armazenada * no vetor "sys_call_table", e tem "NR_syscalls" entrada (normalmente 256). * Mas nem todas as entradas sao definidas. * NR_syscalls e o limite estatico do numero maximo de system calls implemetaveis. * Isto nao indica que o numero atual de system calls implementada seja este. * As entradas na "sys_call_table" que nao contem uma system call associada, contem * "sys_ni_syscall", que e uma funcao que retorna o erro "-ENOSYS" * Deste modo a entrada numero n na "sys_call_table" contem o endereco da rotina da * system call tendo como numero n. * * Para adicionar uma nova system call, e como sequestrar uma system call. * Voce tem que substituir uma entrada na sys_call_table. So que voce * vai usar uma entrada que nao seje usada, alguma entrada como por exemplo * a 226 ou mais alta, ou seja, alguma entrada que tenha "sys_ni_syscall" * * * Para mais detalhes de uma olhada nestes arquivos : * * /usr/src/linux/arch/i386/kernel/entry.S * /usr/src/linux/include/asm-i386/unistd.h * /usr/src/linux/include/linux/sys.h * * Parte do espaço do usuario : * Para uma aplicacao poder chamar uma system call ela usa algumas macros. * Mais informacoes em /usr/include/asm/unistd.h * Olhe este arquivo e note que nao existem um definida para __NR_my_syscall xx (226) * Assim voce tera que usar as macros definidas em asm/unistd.h (/usr/include/asm/unistd.h) * * Pequeno exemplo de um prog para chamar a system call adicionada neste modulo. *------------------------------------------------------------------------------ * #include <asm/unistd.h> // _syscallX macro * #include <errno.h> * * #define __NR_my_newsyscall 226 // numbero da nossas syscall na sys_call_table * * _syscall1(int,my_newsyscall,int,x) //depende do numero de argumentos da nossa system call * // neste exemplo e apenas 1 argumento * * main(){ * int i; * * i=my_newsyscall(100); * printf("Valor retornado %d\n",i); * } *----------------------------------------------------------------------------- * Qualquer duvida, sugestao, ou algum erro: mail thobias@cos.ufrj.br * 04/12/2001 */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/unistd.h> #include <asm/uaccess.h> #include <linux/sched.h> #define NUM_SYSCALL 226 //entrada na sys_call_table para interceptar (entrada nao usada) asmlinkage long (*original_call)(void); asmlinkage int my_syscall(int x) { MOD_INC_USE_COUNT; printk(KERN_ALERT "yeah, Estou aqui\n"); printk(KERN_ALERT "Valor = %d\n",x); MOD_DEC_USE_COUNT; return x; } int add_init_module(void) { extern long sys_call_table[]; printk(KERN_ALERT "Hello !\n"); printk(KERN_ALERT "Interceptar system call numero %d !\n",NUM_SYSCALL); /* Salva endereco da rotina original */ original_call = (long (*)(void))(sys_call_table[NUM_SYSCALL]); /* subistitui pela nossa system call */ sys_call_table[NUM_SYSCALL] = (unsigned long)my_syscall; printk(KERN_ALERT "syscall interceptada \n"); return 0; } void add_cleanup_module(void) { extern long sys_call_table[]; printk(KERN_ALERT "Goodbye !\n"); /* restaura endereco original */ sys_call_table[NUM_SYSCALL] = (unsigned long)original_call; printk(KERN_ALERT "Syscall numbero %d restaurada\n",NUM_SYSCALL); } module_init(add_init_module); module_exit(add_cleanup_module); MODULE_DESCRIPTION("kernel module adiciona system call"); MODULE_AUTHOR("Thobias Salazar Trevisan"); MODULE_LICENSE("GPL"); EXPORT_NO_SYMBOLS;