Chamadas do sistema suportadas na execução do Kernel

9

Existe uma maneira de obter o número ou a lista de chamadas do sistema suportadas pelo Linux Kernel atualmente em execução? Então, eu quero encontrar uma maneira de 'ler' a tabela syscall de um kernel em execução.

Swair
fonte

Respostas:

15

O arquivo /proc/kallsymslista todos os símbolos do kernel em execução. Por convenção, as chamadas do sistema têm um nome que começa com sys_. Em um sistema de 64 bits, as chamadas de sistema para programas de 32 bits têm um nome que começa com sys32_. Estritamente falando, isso lista as funções internas do kernel, não a chamada do sistema, mas acho que a correspondência funciona (toda chamada de sistema chama uma função interna do kernel para fazer o trabalho, e acho que o nome é sempre o nome da chamada do sistema com o sys_prefixo )

</proc/kallsyms sed -n 's/.* sys_//p'

Geralmente, essas informações não são úteis, porque as chamadas do sistema mudam muito lentamente. Componentes opcionais fornecem funcionalidade em termos de chamadas de sistema existentes, usando recursos gerais, como dispositivos (com ioctl quando reade writenão o cortam), sistemas de arquivos, soquetes etc. A determinação da lista de chamadas de sistema suportadas não informa nada sobre os recursos que o sistema suporta. Outros nomes de funções internas também não ajudam, porque eles mudam muito rapidamente: o nome da função que implementa algum recurso em uma versão do kernel pode mudar na versão seguinte.

Gilles 'SO- parar de ser mau'
fonte
+1. Agora foi isso que eu quis dizer quando disse: "Vou deixar alguém com mais experiência do que eu te responder" . Além disso, como /proc/kallsymspode ser manipulado como qualquer outro arquivo, torna-se bastante fácil usá-lo em um programa.
John WH Smith
2
@JohnWHSmith “Pode ser manipulado como qualquer outro arquivo”… com a ressalva de que em sistemas com ASLR do kernel, esse arquivo deve ser legível apenas pela raiz.
Gilles 'SO- stop be evil'
7

TL; DR

Eu continuava encontrando novas alternativas ao escrever esta resposta, então apenas escrevi alguns detalhes sobre cada uma delas e fiz algumas estatísticas. Basicamente, você pode:

  • Leia a resposta de Gilles, que fornece uma maneira limpa e rápida de fazê-lo (depende /proc).
  • Use os recursos da documentação.
  • Use os arquivos de cabeçalho C do seu sistema.
  • Use o próprio código fonte do kernel.
  • Use o /sysdiretório

Depois de fazer as contas, eu recomendaria (entre as minhas alternativas) o uso do /syssistema de arquivos, pois parece dar o melhor resultado em termos de número de chamadas do sistema. Você pode pular direto para essa seção se não quiser ler sobre os outros truques.

Usando os recursos da documentação

Embora você possa perder algumas delas, você pode usar apropospara listar todas as páginas de manual pertencentes à seção 2 (chamadas do sistema):

$ apropos -s2 . | awk '{print $1}' | column

Remova columnse você não deseja uma saída em colunas sofisticada.

Acabei de descobrir, mas há uma página de manual do Linux sobre chamadas de sistema, e você poderá encontrar a maioria delas.

$ man syscalls

Eu também me deparei com esses dois sites que poderiam ser interessantes:

Usando arquivos de cabeçalhos

Edit: Agora, quando se trata de determinar programaticamente (ou pelo menos, sem depender de recursos documentados) quais chamadas de sistema estão disponíveis, receio que o kernel não mantenha uma tabela de suas chamadas de sistema, pelo menos não sob a forma de uma lista de strings (como você provavelmente esperaria manipulá-las). Nesse nível, estamos falando mais sobre endereços e ponteiros de funções, em vez de nomes de funções.

Acabei de navegar no meu /usr/includediretório e grep-ed algumas coisas: você pode achar os seguintes diretórios interessantes. Alguns deles podem ser diferentes em sua máquina, dependendo da arquitetura e distribuição, mas tenho certeza de que você poderá adaptá-los.

  • / usr / include / linux
  • / usr / include / x86_64-linux-gnu
  • / usr / include / sys
  • / usr / include / asm-generic

Ao procurar definições de funções neste arquivo, você encontrará muitas chamadas do sistema, mesmo que elas não sejam totalmente definidas lá. Corri alguns greps nesses diretórios e consegui encontrar menções de algumas chamadas de sistema. Aqui está um exemplo:

$ grep 'sys_exit' /usr/include -R
asm-generic/unistd.h:__SYSCALL(__NR_exit, sys_exit)

Então, acho que outra maneira de encontrar alguns deles seria:

$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')'

Usando o código fonte do kernel e sua tabela syscall

Outra solução é usar o próprio código-fonte do kernel (e não apenas os cabeçalhos!) E encontrar uma maneira de pesquisá-lo com eficiência. Como o kernel commit 303395ac3bf3e2cb488435537d416bc840438fcb , você pode achar isso um pouco mais fácil do que antes. Aqui está um exemplo para 3.13 (que é meu kernel):

$ wget https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/syscalls/syscall_64.tbl?id=refs/tags/v3.13 -O syscall_64.tbl

Agora que você obteve a tabela syscalls real, basta navegar nela:

$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl

Você pode encontrar uma maneira, usando unamee arch, de baixar o tblarquivo diretamente do git.kernel.org , com base na versão e na arquitetura do kernel em execução.

Usando o /syssistema de arquivos

A resposta de Gilles me deu um pouco de inspiração, e você pode encontrar essas chamadas de sistema lá dentro /sys/kernel/debug/tracing/events/syscalls. Este diretório é usado para monitorar o uso de cada chamada do sistema. Cada syscall possui dois diretórios:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

Portanto, o uso ls, grepe cut...

$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3

Estatísticas

No meu sistema:

  • O uso das páginas do manual revelou 440 chamadas do sistema.
  • grep- __SYSCALLnos arquivos de cabeçalho revelou 212 chamadas de sistema.
  • A leitura da tabela syscalls a partir das fontes do kernel revelou 346 chamadas de sistema.
  • Usando /sys290 chamadas de sistema reveladas.

Agora, se eu juntar tudo ...

$ apropos -s2 . | awk '{print $1}' > system_calls.txt
$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')' >> system_calls.txt
$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl >> system_calls.txt
$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3 >> system_calls.txt

$ sort < system_calls.txt | uniq | wc -l
707

Lá vamos nós, 707 chamadas de sistema! Obviamente, esse número reflete uma definição muito flexível de "chamada do sistema", pois o 3.13 deve fornecer apenas 274 chamadas do sistema (a leitura /sysparece ser a solução mais próxima).

John WH Smith
fonte
Eu estou procurando uma maneira mais em termos de 'ler' a tabela de chamadas do sistema, de alguma forma, em vez de descobrir qual das chamadas do sistema estão documentados em páginas man
Swair
Eu não acho que o kernel mantenha uma lista de syscalls, pelo menos não como uma lista de strings. Eu editei minha resposta. Se há uma maneira real de fazer isso, eu vou deixar alguém com mais experiência do que eu lhe responder;)
John WH Smith
então fiquei pensando sobre isso depois de adicionar uma chamada de sistema ao kernel e tentar usá-la fornecendo "função não implementada", e me perguntei se havia alguma maneira de obter a tabela syscall para o kernel atual. quando eu faço '#make install', atualizo o grub e inicio um novo kernel, em que etapa o novo kernel se torna relevante inclui arquivos que contêm a nova chamada do sistema?
Swair
1
Se a chamada do sistema não for encontrada, você não a implementou corretamente. Minha resposta diz como encontrar chamadas do sistema Linux, mas não como depurar as suas próprias (já que não é o que você está pedindo). Se estiver com problemas para desenvolvê-lo, faça uma pergunta especificamente sobre ele e evite o problema XY .
John WH Smith
@swair É altamente incomum adicionar funcionalidades adicionando uma chamada do sistema. Não podemos ter certeza do que está errado, pois você não forneceu nenhum código (e, se sua pergunta exigir código C, não é um tópico aqui, mas em casa no Stack Overflow ). Eu suspeito que você implementou uma chamada do sistema (corretamente ou não) e que você está tentando usá-la em um programa em C, e que está perdendo a etapa de escrever uma função em C que faz a chamada do sistema. Uma chamada do sistema não é uma chamada de função comum.
Gilles 'SO- stop be evil'
1

Todas as respostas estão bem.

Se você estiver procurando por um nome de chamada do sistema específico:

$ cat /proc/kallsyms | grep <sys_call_name>

Se você está procurando uma lista de todas as chamadas do sistema:

$ cat /proc/kallsyms
Hamed Kamrava
fonte