Fondo

Fondo

Para los fines de esta pregunta, supongamos que hay un archivo ( /path/to/file) en el sistema de archivos con un contenido determinado como este:

$> cat /path/to/file
this is the content of the
file /path/to/file 

Estoy contento con casi todos los procesos en ejecución (y con acceso de lectura a este archivo), leyendo este contenido.
Sin embargo, debería (y este es el meollo de la pregunta) ser un proceso específico, que al leerlo /path/to/filedebe recibir un contenido de archivo diferente.

$> cat /path/to/file
this is the DIFFERNT content of the
file /path/to/file 

¿Cómo puedo falsificar de alguna manera el contenido del archivo para un proceso específico?

Algunas conjeturas mías sobre qué camino tomar serían soluciones relacionadas con:

  • truco de enlace simbólico
  • (Linux) truco de espacios de nombres (espacio de nombres del sistema de archivos)
  • chroottruco
  • $LD_PRELOADtruco de enganche
  • superposiciones

Mi plataforma es GNU/linux, pero si hay una forma POSIX de lograrlo sería aún mejor :)

Actualizar

¿Cuál sería una buena solución/respuesta?

Un criterio para una buena solución/respuesta sería que sea posible lograr "contenido de archivo diferente para un proceso específico", sin necesidad de la interacción del usuario root, aunque lo ideal es que el usuario no pueda escribir en el archivo falsificado en primer lugar.

Otro buen criterio sería que la modificación del proceso de archivo que se muestra al proceso sea específica e idealmente sin ningún tipo de condición de carrera.

Fondo

Mozilla firefox usa 2 archivos zip /usr/lib/firefox/omni.jay /usr/lib/firefox/browser/omni.ja, que contienen una buena cantidad de código de Firefox (principalmente el material escrito en Javascript), al falsificar el archivo podría modificar mi versión de Firefox (incluir algunas características que ya no puedo implementar como extensión, proporcionó soporte XPCOM eliminado y no le gustó la coerción de instalación de complementos)

Respuesta1

Sí, montar espacios de nombres es un enfoque:

$ cat file
foo
$ cat other-file
bar
$ sudo unshare -m zsh -c 'mount --bind other-file file; USERNAME=$SUDO_USER; cat file'
bar
$ cat file
foo

Arriba se usa zshpara restaurar el uid/gids del usuario original para el comando cat secuestrado.

Respuesta2

He aquí una manera de hacerlo conprecargainsertar algo de código entre el programa y la biblioteca del sistema, mediante un pequeño fragmento de código. Esto supone que el programa es un binario vinculado dinámicamente, o un script ejecutado por un binario vinculado dinámicamente (es decir, no está vinculado estáticamente). Escriba el siguiente código en un archivo override_fopen.c:

#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifndef FROM
#error "Define FROM to the path to override in double quotes, e.g. -DFROM='\"/bad\"'"
#endif
#ifndef TO
#error "Define TO to the path to use instead in double quotes, e.g. -DFROM='\"/good\"'"
#endif
FILE *fopen(const char *path, const char *mode) {
    void *(*original_fopen)(const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    return original_fopen(path, mode);
}
int open(const char *path, int oflag, ...) {
    int (*original_open)(const char *, int, ...) = dlsym(RTLD_NEXT, "open");
    int ret;
    va_list args;
    if (!strcmp(path, FROM)) {
        path = TO;
    }
    va_start(args, oflag);
    if (oflag & O_CREAT) {
        ret = original_open(path, oflag, (mode_t)va_arg(args, mode_t));
    } else {
        ret = original_open(path, oflag);
    }
    va_end(args);
    return ret;
}

Compile con el siguiente comando (eso es para Linux, otras variantes de Unix pueden requerir opciones diferentes). Tenga en cuenta las comillas alrededor de la ruta que desea anular.

gcc -DFROM='"/path/to/file"' -DTO='"/path/to/alternate/content"' -D_GNU_SOURCE -O -Wall -fPIC -shared -o override_fopen.so override_fopen.c -ldl

Ejecute el programa de la siguiente manera (en OSX, utilícelo DYLD_PRELOADen lugar de LD_PRELOAD):

LD_PRELOAD=./override_fopen.so ./myexe

Esto solo funciona si el programa llama a la función de biblioteca fopeno open. Si llama a alguna otra función, deberá anularla. Puedes usarltracepara ver qué llamadas de biblioteca hace el programa.

información relacionada