Uma System Call é usada quando um aplicativo necessita que uma certa tarefa seja realizada no sistema operacional ou no ambiente dele e que seja necessário o modo ROOT ou administrador para realizá-la. No Linux tudo passa pelo controle do sistema operacional e cada programa só tem acesso ao seu ambiente virtual, nada mais. Para obter acessos a outros ambientes do sistema, você precisa ser ROOT e no Linux, como você já deve saber, você não usa o usuário ROOT, isto é, não opera sobre o modo administrador o tempo todo, apenas quando necessário. Isso aumenta muito a segurança do sistema.
No sistema operacional da Microsoft uma aplicação pode ter acesso privilegiado ao sistema sem a permissão do usuário, e a conclusão disso são vírus, spywares, worms wtc.
Esse artigo tem como objetivo ensinar a criar uma System Call simples para um sistema 32 bits e 64bits. Pode parecer algo muito complicado a ser fazer, mas você verá o quão simples é. Infelizmente não é possível implementar uma System Call no sistema operacional da Microsoft. O motivo? O código dele é fechado.
- Você precisará do fonte do Kernel. Normalmente o sistema salva o código do Kernal mais novo instalado em seu sistema no diretório “/usr/src/”, contudo você também poderá baixá-lo do site abaixo::
http://www.kernel.org/ - Vamos implementar uma System Call que imprime quantas vezes ela foi chamada no sistema. Vá até o diretório principal do código fonte do Kernel escolhido. Irei supor que o diretório é o: /usr/src/linux/
- Abra o arquivo “/usr/src/linux/kernel/sys.c”. Lembre-se que você está em um diretório que exige o modo ROOT para editar arquivos. Adicione ao final do arquivo:
asmlinkage int sys_minhaSys() { int static contador_minhaSys = 0; printk(KERN_EMERG "A minha SysCall foi chamada %d vez(es)!\n", contador_minhaSys++); return 0; /* estou retornando zero apenas para depois verificar qual o retorno da syscall, pois se o printk der erro, ele retornará -1 */ }
- Agora vem ao caso explicar o “printk”. Equivalente ao “printf”, mas para a camada do Kernel. A mensagem será impressa no final do seguinte log: /var/log/syslog. Outro modo de visualizar é digitando “dmesg” no terminal. O “KERNEL_EMERG” é para identificar os tipos de mensagem no Kernel. Não importa no nosso caso qual deles usar. Não informá-lo implicará no uso de um level padrão de mensagem, determinado no código do Kernel.
- Ainda no mesmo arquivo, insira a seguinte include junto às outras includes:
#include <linux/linkage.h> - Agora abra o seguinte arquivo: /usr/src/linux/arch/x86/include/asm/unistd_32.h
Dica: Se você estiver compilando para 64 bits, será o arquivo unistd_64.h - Procure pela última SystemCall (estarão todas em sequência com um número denotando a sequência). Procure pelo maior número. Logo abaixo dessa última System Call adicione o seguinte código para 32 ou 64 bits:
#define __NR_minhaSys número_da_anterior_+_1 - No caso do 32 bits, mais uma alteração será necessária, no mesmo arquivo. Note a existência da linha “#define NR_syscalls algum_número” logo abaixo de todas as SystemCalls. Ela diz quantas SystemCall existem no código. Basta somar 1 ao “algum_número”, afinal você criou uma SystemCall extra no sistema.
- Agora abra o arquivo: /usr/src/linux/arch/x86/include/asm/syscalls.h
Importante: Existem os arquivos “syscalls.h” e “syscall.h”; Abra o que possui a letra “s”. - No caso de sistema 32 bits, procure pela linha que contém “/* X86_32 only */” e abaixo dela insira o seguinte código:
asmlinkage int sys_minhaSys();
No caso de sistema 64 bits, procure pela linha que contém “/* X86_64 only */” e aplique o mesmo procedimento do caso do 32bits.
- Agora abra o seguinte arquivo para 32 0u 64 bits: /usr/src/linux/arch/x86/kernel/syscall_table_32.h
Insira no final do arquivo:.long sys_minhaSys - Pronto, agora basta compilar o seu Kernel. Você pode encontrar um tutorial atualizado e de fácil entendimento aqui mesmo, no siste do gerencievocemesmo.com.br.
Depois de compilado e instalado o Kernel, você deverá reiniciar a máquina para carregar o Kernel que você modificou. Agora irei criar uma aplicação simples para que você possa testar se a sua SystemCall está funcionando.
Programa:
#include <sys/syscall.h> #include <unistd.h> #include <stdio.h> #define __NR_minhaSys 338 /* troque 338 pelo número de sua SystemCall */ int meuTeste() { return (int) syscall(__NR_minhaSys); }; main () { printf("\nSe a minha SystemCall falhar, o resultado será -1. Se retornar corretamente, o resultado será 0.\n O Resultado foi: %d\n", meuTeste()) printf("\n Se o resultado deu zero, agora você pode verificar se a sua SystemCall imprime quantas vezes ela foi chamada.\nDigite "dmesg | tail" ou "tail /var/log/syslog" para verificar!\n"); }
Basta agora compilá-lo e executá-lo.