como alterar o conteúdo de um arquivo apenas para um processo específico?

5

Para o propósito 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 tendo acesso de leitura a este arquivo), lendo este conteúdo.
No entanto, deve haver ( e este é o núcleo da questão ) um processo específico, que ao ler /path/to/file deve receber um conteúdo de arquivo diferente.

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

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

Algumas das minhas suposições, qual caminho a ser seguido, seriam as solições relacionadas a:

  • truque de ligação simbólica
  • (linux) namespaces (namespace do sistema de arquivos) truque
  • chroot truque
  • $LD_PRELOAD truque de engate
  • overlayfs

Minha plataforma é GNU / linux, mas se houver uma maneira POSIX para alcançá-la, seria ainda melhor:)

Atualizar

Qual seria uma boa solução / resposta?

Um critério para uma boa solução / resposta seria que é possível obter "conteúdo de arquivo diferente para um processo específico", sem precisar da interação do usuário raiz, mesmo que o ideal seja que o arquivo falsificado não pode 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 um tipo de condição de corrida.

Antecedentes

O Mozilla firefox usa 2 arquivos zip /usr/lib/firefox/omni.ja e /usr/lib/firefox/browser/omni.ja , que contêm uma quantidade razoável de código do firefox (principalmente o material escrito em Javascript), falsificando o arquivo eu seria capaz de modificar minha versão do firefox ( incluir alguns recursos que não posso mais implementar como uma extensão, desde o suporte XPCOM abandonado e que não goste de coerção de addon-siging)

    
por humanityANDpeace 25.04.2017 / 15:49

2 respostas

7

Sim, os namespaces de montagem são 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 de usar zsh para restaurar os uid / gids do usuário original para o comando cat sequestrado.

    
por 25.04.2017 / 16:28
4

Aqui está uma maneira de fazer isso com o pré-carregamento para colocar algum código entre o programa e a biblioteca do sistema, por um pequeno pedaço de código. Isso pressupõe que o programa é um binário vinculado dinamicamente, ou um script executado por um binário vinculado dinamicamente (ou seja, ele 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 o 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_PRELOAD em vez de LD_PRELOAD ):

LD_PRELOAD=./override_fopen.so ./myexe

Isso só funciona se o programa estiver chamando a função de biblioteca fopen ou open . Se ele chamar outra função, você precisará substituir essa. Você pode usar ltrace para ver que biblioteca chama o programa.

    
por 26.04.2017 / 02:28