Varias formas de llamar a una syscall en C
Como trabajo inicial de la asignatura Linux Kernel & Hackers Hut, después de la primera clase nos mandó hacer un pequeño programa en C que creara un directorio, de tres formas distintas: con la llamada correspondiente de la libc, con la función syscall de libc y saltándose la libc por completo.
Las dos primeras formas son bastante sencillas... vamos a ver el ejemplo de mkdir. En el primer caso, haríamos una simple llamada como ésta:
#include <sys/stat.h>
#include <sys/types.h>
[...]
mkdir(argv[1],0777);
Donde argv[1] es el nombre del directorio y 0777 son los permisos dados en notación octal.
En el segundo caso, simplemente necesitamos saber que la llamada al sistema se llama mkdir y que las constantes con los nombres de las llamadas al sistema tienen la forma SYS_xxxx, con xxxx el nombre de la llamada. Es importante esto, pues yo estaba usando __NR_mkdir tal y como se llama en el kernel 😳 .
#include <sys/syscall.h>
#include <unistd.h>
[...]
syscall(SYS_mkdir,argv[1],0777);
Finlamente, la última es un poco más especial. Necesitamos saber: tipo del valor de retorno, número de parámetros y sus tipos, así como el nombre de la llamada al sistema. Las macros se llaman _syscallX, donde la X va de 1 a 5 según el tipo de parámetros.
Así pues, sabiendo la llamada al sistema que queremos hacemos un man 2
#include <linux/unistd.h>
#include <sys/types.h>
#include <errno.h>
//Dirty hack so it compiles on my x86_64 machine
#ifndef MAX_ERRNO
#define MAX_ERRNO 4095
#endif
_syscall2(int,mkdir,const char *, pathname, mode_t, mode);
int main(int argc, char **argv){
return mkdir(argv[1],0777);
}
En mi caso he tenido que añadir ese define condicional puesto que no compilaba debido a que la constante MAX_ERRNO no estaba definida. Busqué en google y parece ser que es un fallo en la libc para x86_64, al menos en la versión que yo tengo así es.
Las dos últimas formas son interesantes para cuando se añade una llamada al sistema que queremos usar y la libc no nos ofrece todavía un wrapper para ella, con lo que la debemos llamar a mano. Otra opción sería meter un poco de inline assembly, pero teniendo estas opciones me parece que es un poco bestia hacerlo, además de que se vuelve dependiente de la arquitectura, lo cual no es muy bueno... a no ser que necesitemos velocidad o control máximo y así lo podamos ganar, que tampoco sé la diferencia de velocidad entre usar la macro _syscallX y llamar directamente a la syscall desde ensamblador.
Por último, comentar que si la llamada al sistema tiene más de 5 parámetros no se pueden usar las macros, sino que se deben poner los parámetros en la pila y pasando un único parámetro: un puntero al bloque de argumentos en la pila.
Notar también que es interesante conocer ambos métodos, porque dependiendo de la libc que se use puede que se tenga la función syscall() o no, y si no la tenemos deberemos apoyarnos en las macros para hacer las llamadas.
September 13th, 2007 - 23:14
buena explicación!
por cierto la página de tu profe muy hacker xDD
mira a ver si en el segundo ejemplo te vas al System.map a pillar la dirección jajaja xD =>
$ grep mkdir /usr/src/linux/System.map
ffffffff8026ef5f t shmem_mkdir
ffffffff8027cee5 T vfs_mkdir
ffffffff8027f3d9 T sys_mkdirat
ffffffff8027f4b8 T sys_mkdir
ffffffff80288730 t bad_inode_mkdir
ffffffff802abd32 T proc_mkdir_mode
ffffffff802abd94 T proc_mkdir
ffffffff802b891c t reiserfs_mkdir
ffffffff802df8b0 t ext3_mkdir
ffffffff802f2fcb t ext2_mkdir
ffffffff802f7706 t ramfs_mkdir
ffffffff802f7d43 t hugetlbfs_mkdir
ffffffff802ffde9 t msdos_mkdir
ffffffff80301302 t vfat_mkdir
ffffffff80307aed t nfs_mkdir
ffffffff8030e553 t nfs_proc_mkdir
ffffffff80313f9b t nfs3_proc_mkdir
ffffffff80315210 t nfs3_xdr_mkdirargs
ffffffff8031798f t nfsd_proc_mkdir
ffffffff803210e4 t nfsd3_proc_mkdir
ffffffff803221d1 T nfs3svc_decode_mkdirargs
ffffffff8032bb6d T smb_proc_mkdir
ffffffff8032e6a6 t smb_mkdir
ffffffff80340150 t autofs4_dir_mkdir
ffffffff80348c22 t udf_mkdir
ffffffff804b14ed T oprofilefs_mkdir
ffffffff805269b3 T rpc_mkdir
ffffffff80665880 r __ksymtab_vfs_mkdir
ffffffff80666ab0 r __ksymtab_proc_mkdir
ffffffff806722e8 r __kcrctab_vfs_mkdir
ffffffff80672c00 r __kcrctab_proc_mkdir
ffffffff8067be1d r __kstrtab_vfs_mkdir
ffffffff8067d852 r __kstrtab_proc_mkdir
September 22nd, 2007 - 21:42
Mucha suerte en tu periplo erasmus
September 24th, 2007 - 10:27
¡Ay! Miedo me da que no estés haciendo caso de lo que te dije, menos whitehackear y más Erasmusear.
En fín, ¡nos vemos en el CCC!
September 24th, 2007 - 19:04
gran congreso!!
No se ven afectados por las absurdas leyes alemanas???
http://freeworld.thc.org/welcome/press.html thc.org ha partido su web por ello
September 24th, 2007 - 19:05
0x7265646f63 , don’t worry, hay tiempo para todo 😉
Ahora mismo estoy en mi pueblo ( había que venir a fiestas, que empiezan en serio mañana 🙄 ) pero cuando vuelva para allá (el domingo) erasmusearé todo lo que pueda 😛
November 27th, 2007 - 11:28
Hola, soy alumno de la ETSIT (UPV) y estoy pensando irme el año que viene de erasmus a Eindhoven para hacer el PFC, he leido que te está costando encontrarlo, me agregas al msn y así me informas de algunas cosillas?? carrodug@hotmail.com
Muchas gracias.
Buen trabajo con el blog 🙂