Llamadas del sistema admitidas al ejecutar Kernel

9

¿Hay alguna manera de obtener el número o la lista de llamadas al sistema admitidas por el kernel de Linux que se ejecuta actualmente? Así que quiero encontrar una manera de 'leer' la tabla syscall de un kernel en ejecución.

Swair
fuente

Respuestas:

15

El archivo /proc/kallsymsenumera todos los símbolos del núcleo en ejecución. Por convención, las llamadas al sistema tienen un nombre que comienza con sys_. En un sistema de 64 bits, las llamadas al sistema para programas de 32 bits tienen un nombre que comienza con sys32_. Hablando estrictamente, esto enumera las funciones internas del kernel, no la llamada al sistema, pero creo que la correspondencia funciona (cada llamada al sistema invoca una función interna del kernel para hacer el trabajo, y creo que el nombre siempre es el nombre de la llamada al sistema con sys_prefijo )

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

Esto generalmente no es información útil, porque las llamadas al sistema cambian muy lentamente. Los componentes opcionales proporcionan funcionalidad en términos de llamadas al sistema existentes, utilizando funciones generales como dispositivos (con ioctl cuando ready writeno lo corta), sistemas de archivos, sockets, etc. Determinar la lista de llamadas al sistema compatibles no le dirá nada sobre las características que el sistema soporta. Otros nombres de funciones internas tampoco ayudarán porque estos cambian muy rápidamente: el nombre de la función que implementa alguna característica en una versión del kernel puede cambiar en la próxima versión.

Gilles 'SO- deja de ser malvado'
fuente
+1. Eso es lo que quise decir cuando dije "Dejaré que alguien con más experiencia que yo te responda" . Además, dado que /proc/kallsymspuede manipularse como cualquier otro archivo, resulta bastante fácil usarlo en un programa.
John WH Smith
2
@JohnWHSmith "Se puede manipular como cualquier otro archivo" ... con la advertencia de que en sistemas con kernel ASLR, este archivo debe ser legible solo por root.
Gilles 'SO- deja de ser malvado'
7

TL; DR

Seguí encontrando nuevas alternativas al escribir esta respuesta, así que solo escribí un poco de detalles sobre cada una de ellas e hice algunas estadísticas. Básicamente, puedes:

  • Lea la respuesta de Gilles, que proporciona una forma limpia y rápida de hacerlo (se basa en /proc).
  • Use los recursos de documentación.
  • Use los archivos de encabezado C de su sistema.
  • Use el código fuente del núcleo en sí.
  • Usa el /sysdirectorio.

Después de hacer los cálculos, recomendaría (entre mis alternativas) usar el /syssistema de archivos, ya que parece dar el mejor resultado en términos de número de llamadas al sistema. Puedes saltar directamente a esa sección si no quieres leer sobre los otros trucos.

Usando los recursos de documentación

Si bien puede perder algunos de ellos, puede usarlos apropospara enumerar todas las páginas de manual que pertenecen a la sección 2 (llamadas al sistema):

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

Elimine columnsi no desea una salida elegante en columnas.

Lo acabo de descubrir, pero hay una página de manual de Linux sobre llamadas al sistema, y ​​podrás encontrar la mayoría de ellas en él.

$ man syscalls

También encontré estos dos sitios web que podrían ser interesantes:

Usar archivos de encabezados

Editar: ahora, cuando se trata de determinar programáticamente (o al menos, sin depender de características documentadas) determinar qué llamadas al sistema están disponibles, me temo que el núcleo no mantiene una tabla de sus llamadas al sistema, al menos no bajo la forma de una lista de cadenas (como probablemente esperarías manipularlas). En este nivel, estamos hablando más sobre direcciones de funciones y punteros, en lugar de nombres de funciones.

Acabo de navegar por mi /usr/includedirectorio y grepagregué algunas cosas: podría encontrar interesantes los siguientes directorios. Algunos de ellos pueden ser diferentes en su máquina, dependiendo de su arquitectura y distribución, pero estoy seguro de que podrá adaptarlos.

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

Al buscar definiciones de funciones en este archivo, encontrará muchas llamadas al sistema, a pesar de que no estarán completamente definidas allí. Ejecuté algunos greps en estos directorios y pude encontrar menciones de algunas llamadas al sistema. Aquí hay un ejemplo:

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

Entonces, supongo que otra forma de encontrar algunos de ellos sería:

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

Usando el código fuente del núcleo y su tabla syscall

Otra solución es usar el código fuente del núcleo en sí (¡y no solo los encabezados!), Y encontrar una manera de buscarlo de manera eficiente. Dado que el kernel confirma 303395ac3bf3e2cb488435537d416bc840438fcb , puede que encuentre esto un poco más fácil que antes. Aquí hay un ejemplo para 3.13 (que es mi 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

Ahora que tiene la tabla de llamadas al sistema reales, simplemente búsquela:

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

Puede encontrar una manera, usando unamey arch, para descargar el tblarchivo directamente desde git.kernel.org , en función de la versión y arquitectura del kernel en ejecución.

Usando el /syssistema de archivos

La respuesta de Gilles me dio un poco de inspiración, y puede encontrar esas llamadas al sistema en su interior /sys/kernel/debug/tracing/events/syscalls. Este directorio se utiliza para monitorear el uso de cada llamada del sistema en el sistema. Cada syscall tiene dos directorios:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

Por lo tanto, el uso ls, grepy cut...

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

Estadísticas

En mi sistema:

  • El uso de las páginas de manual reveló 440 llamadas al sistema.
  • grep-ing __SYSCALLen los archivos de encabezado reveló 212 llamadas al sistema.
  • La lectura de la tabla syscalls de las fuentes del núcleo reveló 346 llamadas al sistema.
  • Usando /sys290 llamadas al sistema reveladas.

Ahora, si reúno todo ...

$ 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

¡Allá vamos, 707 llamadas al sistema! Por supuesto, este número refleja una definición muy flexible de una "llamada al sistema", ya que se supone que 3.13 proporciona solo 274 llamadas al sistema (la lectura /sysparece ser la solución más cercana).

John WH Smith
fuente
Estoy buscando una manera más en términos de 'leer' la tabla de llamadas al sistema de alguna manera en lugar de descubrir cuáles de las llamadas al sistema están documentadas en las páginas de
manual
No creo que el kernel mantenga una lista de sus llamadas al sistema, al menos no como una lista de cadenas. Edité mi respuesta. Si hay una manera real de hacer esto, dejaré que alguien con más experiencia que yo te responda;)
John WH Smith
así que me preguntaba sobre esto después de agregar una llamada al sistema al kernel y al intentar usarlo estaba dando "función no implementada", y me preguntaba si había alguna forma de obtener la tabla syscall para el kernel actual. cuando hago '#make install', actualizo grub e inicio un nuevo kernel, ¿en qué paso se vuelve relevante el nuevo kernel que incluye archivos que contienen la nueva llamada al sistema?
Swair
1
Si no se encuentra su llamada al sistema, entonces no la implementó correctamente. Mi respuesta te dice cómo encontrar las llamadas al sistema de Linux, pero no cómo depurar las tuyas (ya que no es lo que estás pidiendo). Si tiene problemas para desarrollarlo, debe hacer una pregunta específica al respecto y evitar el problema XY .
John WH Smith
@swair Es muy inusual agregar funcionalidad agregando una llamada al sistema. No podemos decir con certeza qué está mal, ya que no proporcionó ningún código (y si su pregunta requiere código C, está fuera de tema aquí, pero en casa en Stack Overflow ). Sospecho que implementó una llamada al sistema (correctamente o no) y que está tratando de usarla desde un programa en C, y que se está perdiendo el paso de escribir una función en C que realiza la llamada al sistema. Una llamada al sistema no es una llamada de función ordinaria.
Gilles 'SO- deja de ser malvado'
1

Todas las respuestas están bien.

Si está buscando un nombre de sistema específico:

$ cat /proc/kallsyms | grep <sys_call_name>

Si está buscando una lista de todas las llamadas al sistema:

$ cat /proc/kallsyms
Hamed Kamrava
fuente