jueves, 25 de abril de 2013

Intermezzo #1

... y entenderás que algo anda mal cuando lo que quieras olvidar sean los momentos felices ; cuando todas las preguntas que importen empiecen con ¿por qué no ...? ; cuando el cubo vacío se te llene de nada hasta que te engorde el orgullo ; cuando a mitad del camino tengas mil pasados y ningún futuro . Pero estarás peor cuando escribas en abril lo que debías decir en agosto porque febrero no existe .

miércoles, 24 de abril de 2013

Breve tutorial sobre LD_PRELOAD

man ld.so

¿Sabía Usted que es posible remplazar por completo las funciones de la librería estándar con copias personalizadas? o.O Este corto artículo trata un tema que, de ser bien utilizado , puede resultar muy poderoso . Podrá conocer lo que se logra con la variable de entorno LD_PRELOAD en GNU/Linux . ¿Qué cosa es ese bicho? No muerde :) . Le invito a seguir leyendo este artículo y suscribirse a este blog mediante RSS para estar informado acerca de temas avanzados de programación y uso de los comandos del shell de los sistemas Unix .

LD_PRELOAD en acción

A modo de ejemplo vamos a cambiar la función fopen y utilizar nuestra propia copia . Lo mismo se puede hacer con otras funciones e.g. printf , scanf , ... Comencemos con un programa simple (prog.c):

#include <stdio.h>

int main(void) {
    printf("Calling the fopen() function...\n");

    FILE *fd = fopen("test.txt","r");
    if (!fd) {
        printf("fopen() returned NULL\n");
        return 1;
    }

    printf("fopen() succeeded\n");

    return 0;
}

En pocas palabras solamente invocamos la función estándar fopen y chequeamos el valor de retorno . Vamos a compilar y ejecutar .

$ ls
prog.c  test.txt

$ gcc prog.c -o prog

$ ls
prog  prog.c  test.txt

$ ./prog
Calling the fopen() function...
fopen() succeeded

Por otra parte compilamos una versión personalizada de la función fopen y la distribuimos por separado :

#include <stdio.h>

FILE *fopen(const char *path, const char *mode) {
    printf("Always failing fopen\n");
    return NULL;
}

Llamamos a este fichero nullfopen.c y lo compilamos como una librería nullfopen.o .

$ gcc -Wall -fPIC -shared -o nullfopen.so nullfopen.c

Ahora ya estamos listos para modificar LD_PRELOAD :

$ LD_PRELOAD=./nullfopen.so ./prog
Calling the fopen() function...
Always failing fopen
fopen() returned NULL

Como se puede constatar se remplazó fopen con una versión que siempre falla . Este truco es muy útil para depurar aplicaciones o remplazar ciertas partes de libc u otra librería que utilice la aplicación . Un uso práctico notable es el comando tsocks , utilizado para dotar las aplicaciones con la capacidad de conectarse a través de un proxy .

Espero tener tiempo pronto y escribir otro artículo acerca de la mecánica interna que hace posible los resultados que se obtienen con la variable LD_PRELOAD . Si está interesado en conocer más acerca de los sistemas Unix le invito a leer otros artículos sobre comandos y suscribirse a este blog mediante RSS para estar al tanto de nuevos temas . Si tiene preguntas no dude en dejar un comentario . Todo es posible simelo pide ...

lunes, 22 de abril de 2013

Cambiando contexto de usuario con sudo y chroot

chroot

Supongamos que desea ejecutar un comando dentro de un chroot como otro usuario. ¿Cómo se hace? En este artículo exploraremos el camino para lograrlo . No es algo evidente . Por tanto iré explicando paso a paso pues lo más importante es familiarizarse con los comandos de los sistemas Unix y entender porqué se hace lo que se hace cuando se hace. Si desea conocer acerca de otros comandos le sugiero leer también otros artículos acerca de comandos Unix . Si este tutorial le resulta interesante le invito a suscribirse a este blog mediante RSS . ¿Listos? ¡ Comenzamos !

Comenzamos echando un vistazo a man chroot . La sinopsis dice que el modo de uso es

$ chroot /new-root-path`

Bien , ya podemos ejecutar un comando dentro de un chroot como root . ¿Cómo hacemos para que cambie de usuario? Para eso está el comando su .

$ chroot /new-root-path su - user

Por ahora todo bien . Ya logramos ejecutar su dentro del chroot como user , pero ... se nos presenta un prompt interactivo . Al leer la documentación de man su la sinopsis dice

$ su - user cmd

¡Perfecto! Combinandolo todo nos queda :

$ chroot /new-root-path su - user sh

Sin embargo todavía nos quedamos dentro de un shell interactivo . ¿Como nos deshacemos del prompt? Al leer man sh aparece la opción sh -c "command args args..." , que lanzará un shell no interactivo y ejecutará el comando con ciertos argumentos . Exaxtmente lo que se buscaba . Combinandolo todo nos queda :

$ chroot /new-root-path su - user sh -c "command args"

Podría parecer que ya está todo bien , pero hay un detalle . Si el usuario tiene un [entorno personalizado] entonces el mismo no se inicializará automáticamente . Hay que hacerlo manualmente .

$ chroot /new-root-path su - user sh -c ". ~/.profile; command args"

Esto hace lo que se pide :

  1. crea un chroot en /new-root-path
  2. ejecuta el comando con ciertos argumentos en ese contexto
  3. devuelve el control a la sesión activa del shell

Pero ... bueno ... como no es aconsejable estar trabajando como root de forma cotidiana , ejecutamos todo esto con sudo

$ sudo chroot /new-root-path su - user sh -c ". ~/.profile; command args"

De esta forma es posible ejecutar ejecutables de fuentes desconocidas y codificar en un entorno seguro .

Si desea conocer otros trucos relacionados con comandos de Unix la inviación esta hecha para que se suscriba a este blog mediante RSS