Fundo

Fundo

Para efeitos desta questão, vamos supor que exista um arquivo ( /path/to/file) no sistema de arquivos com um determinado conteúdo como este:

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

Estou feliz com quase todos os processos em execução (e com acesso de leitura a este arquivo), lendo este conteúdo.
Deveria, no entanto (e este é o cerne da questão) ser um processo específico, que durante a leitura /path/to/filedeve ser fornecido com conteúdo de arquivo diferente.

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

Como posso falsificar o conteúdo do arquivo para um processo específico?

Algumas suposições minhas sobre qual caminho seguir seriam soluções relacionadas a:

  • truque de link simbólico
  • (linux) truque de namespaces (namespace do sistema de arquivos)
  • chroottruque
  • $LD_PRELOADtruque de fisgar
  • sobreposições

Minha plataforma é GNU/linux, mas se houver uma maneira POSIX de conseguir isso seria ainda melhor :)

Atualizar

Qual seria uma boa solução/resposta?

Um critério para uma boa solução/resposta seria que fosse possível obter "conteúdo de arquivo diferente para um processo específico", sem a necessidade da interação do usuário root, mesmo que, idealmente, o arquivo falsificado não deva ser gravável pelo usuário em primeiro lugar.

Outro bom critério seria que a modificação do processo de arquivo mostrado ao processo seja específica e, idealmente, sem tipo de condição de corrida.

Fundo

O Mozilla firefox usa 2 arquivos zip /usr/lib/firefox/omni.jae /usr/lib/firefox/browser/omni.ja, que contêm uma boa quantidade de código do firefox (principalmente o material escrito em Javascript), falsificando o arquivo eu seria capaz de modificar minha versão do firefox (inclui alguns recursos que não posso mais implementar como um extensão, forneceu suporte XPCOM abandonado e não gostou da coerção de assinatura de complementos)

Responder1

Sim, montar namespaces é uma abordagem:

$ 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

Acima, usando zshpara restaurar o uid/gids do usuário original para o comando cat sequestrado.

Responder2

Aqui está uma maneira de fazer isso compré-carregamentocolocar algum código entre o programa e a biblioteca do sistema, por meio de um pequeno trecho de código. Isto assume que o programa é um binário vinculado dinamicamente ou um script executado por um binário vinculado dinamicamente (ou seja, não está vinculado estaticamente). Escreva o seguinte código em um arquivo 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 com o seguinte comando (para Linux, outras variantes do Unix podem exigir opções diferentes). Observe as aspas ao redor do caminho que você deseja substituir.

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

Execute o programa da seguinte maneira (no OSX, use DYLD_PRELOADem vez de LD_PRELOAD):

LD_PRELOAD=./override_fopen.so ./myexe

Isso só funciona se o programa estiver chamando a função da biblioteca fopenou open. Se chamar alguma outra função, você precisará substituí-la. Você pode usarltracepara ver quais chamadas de biblioteca o programa faz.

informação relacionada