É possível falsificar um caminho específico para um processo?

7

Estou tentando executar o ADB em um servidor linux com vários usuários, onde não sou root (para brincar com meu emulador android). O daemon adb grava seus logs no arquivo /tmp/adb.log , que infelizmente parece ser codificado no ADB e nessa situação não vai mudar .

Portanto, o adb não está em execução, apresentando o erro óbvio: cannot open '/tmp/adb.log': Permission denied . Este arquivo é criado por outro usuário e /tmp está com bit de aderência. Se eu iniciar o adb com adb nodaemon server fazendo com que ele grave no stdout, nenhum erro ocorrerá (eu também configurei sua porta para um valor exclusivo para evitar conflitos).

Minha pergunta é: existe alguma maneira de fazer o ADB gravar em outro arquivo diferente de /tmp/adb.log ? Mais geralmente, existe uma maneira de criar um tipo de link simbólico específico do processo? Eu quero redirecionar todos os acessos a arquivo para /tmp/adb.log , dizendo, um arquivo ~/tmp/adb.log .

Novamente, não sou root no servidor, portanto chroot , mount -o rbind e chmod não são opções válidas. Se possível, eu gostaria de não modificar as fontes do ADB, mas certamente, se não houver outras soluções, farei isso.

P.S. Para o caso específico do ADB, posso recorrer à execução de adb nodaemon server com nohup e ao redirecionamento de saída, mas a questão geral ainda é relevante.

    
por gluk47 21.10.2015 / 14:08

2 respostas

3

Aqui está um exemplo muito simples de usar util-linux ' unshare para colocar um processo em um namespace de montagem particular e fornecer uma visão diferente do mesmo sistema de arquivos que seu pai possui atualmente:

{   cd /tmp                      #usually a safe place for this stuff
    echo hey   >file             #some
    echo there >file2            #evidence
    sudo unshare -m sh -c '      #unshare requires root by default
         mount -B file2 file     #bind mount there over hey
         cat file                #show it
         kill -TSTP "$$"         #suspend root shell and switch back to parent
         umount file             #unbind there
         cat file'               #show it
    cat file                     #root shell just suspended
    fg                           #bring it back
    cat file2                    #round it off
}
there                            #root shell
hey                              #root shell suspended
hey                              #root shell restored
there                            #rounded

Você pode dar a um processo uma visão privada de seu sistema de arquivos com o utilitário unshare em sistemas linux atualizados, embora o próprio recurso de namespace de montagem tenha sido bastante maduro para toda a série de kernel 3.x. Você pode inserir namespaces pré-existentes de todos os tipos com nsenter utility do mesmo pacote, e você pode descobrir mais com man .

    
por 21.10.2015 / 17:30
8

LD_PRELOAD não é muito difícil e você não precisa ser root. Interpõe sua própria rotina C que é chamada em vez do open() real na biblioteca C. Sua rotina verifica se o arquivo a ser aberto é "/tmp/adb.log" e chama o real aberto com um nome de arquivo diferente. Aqui está o seu shim_open.c:

/*
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c
 * LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log
 */
#define _FCNTL_H 1 /* hack for open() prototype */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#define OLDNAME "/tmp/adb.log"
#define NEWNAME "/tmp/myadb.log"

int open(const char *pathname, int flags, mode_t mode){
    static int (*real_open)(const char *pathname, int flags, mode_t mode) = NULL;

    if (!real_open) {
        real_open = dlsym(RTLD_NEXT, "open");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    if (strcmp(pathname,OLDNAME)==0) pathname = NEWNAME;
    fprintf(stderr, "opening: %s\n", pathname);
    return real_open(pathname, flags, mode);
}

Compile com gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c e teste-o colocando algo em /tmp/myadb.log e executando %código%. Em seguida, tente o LD_PRELOAD no adb.

    
por 21.10.2015 / 17:23