¿Cómo puedo reimplementar (o empaquetar) una función syscall en Linux?


Supongamos que quiero tomar completamente el control de la llamada al sistema open (), tal vez para envolver el syscall real y realizar algún registro. Una forma de hacer esto es usar LD_PRELOAD para cargar una biblioteca de objetos compartidos (hecha por el usuario) que toma el control del punto de entrada open ().

La rutina open() hecha por el usuario obtiene el puntero a la función glibc open() por dlsym() ing it, y llamándola.

La solución propuesta anteriormente es una solución dinámica, sin embargo. Supongamos que quiero vincular mi propio open() envoltura estática. ¿Cómo lo haría? Supongo que el mecanismo es el mismo, pero también supongo que habrá un choque de símbolos entre el open() definido por el usuario y el libc open().

Por favor, comparta cualquier otra técnica para lograr el mismo objetivo.

Author: Peter Mortensen, 2010-09-08

2 answers

Puede utilizar la función wrap proporcionada por ld. De man ld:

--wrap symbol Utilice una función de envoltura para el símbolo. Cualquier referencia indefinida a symbol se resolverá a __wrap_symbol.

Cualquier referencia indefinida a __real_symbol se resolverá a symbol.

Así que solo tienes que usar el prefijo __wrap_ para tu función wrapper y __real_ cuando quieras llamar a la función real. Un ejemplo simple es:

malloc_wrapper.c:

#include <stdio.h>
void *__real_malloc (size_t);

/* This function wraps the real malloc */
void * __wrap_malloc (size_t size)
{
    void *lptr = __real_malloc(size);
    printf("Malloc: %lu bytes @%p\n", size, lptr);
    return lptr;
}

Aplicación de prueba testapp.c:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    free(malloc(1024)); // malloc will resolve to __wrap_malloc
    return 0;
}

Luego compile la aplicación:

gcc -c malloc_wrapper.c
gcc -c testapp.c
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp

La salida de la aplicación resultante será:

$ ./testapp
Malloc: 1024 bytes @0x20d8010
 58
Author: Giuseppe Cardone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-07 21:53:16

Los símbolos son resueltos por el enlazador en el orden en que los listamos en la línea de comandos, por lo que si listó su biblioteca antes de la biblioteca estándar, tendría precisión. Para gcc, debe especificar

gcc <BLAH> -nodefaultlibs <BLAH BLAH> -lYOUR_LIB <OTHER_LIBS>

De esta manera sus bibliotecas serían buscadas y encontradas primero.

 2
Author: Paul Rubel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-07 21:39:46