프로세스의 특정 경로를 위조하는 것이 가능합니까?

프로세스의 특정 경로를 위조하는 것이 가능합니까?

여러 사용자가 있는 Linux 서버에서 ADB를 실행하려고 하는데 루트가 아닙니다(Android 에뮬레이터를 사용하기 위해). adb 데몬은 로그를 파일에 기록하는데, /tmp/adb.log불행히도 해당 파일은 ADB에 하드코딩되어 있는 것 같습니다.변하지 않을 것이다.

따라서 adb가 실행되지 않고 명백한 오류가 발생합니다 cannot open '/tmp/adb.log': Permission denied. 파일이 다른 사용자에 의해 생성되었으며 /tmp고정 비트가 있습니다. adb를 시작하고 adb nodaemon server이를 stdout에 쓰면 오류가 발생하지 않습니다(충돌을 피하기 위해 해당 포트도 고유한 값으로 설정했습니다).

내 질문은: ADB가 다른 파일에 쓸 수 있는 방법이 있습니까 /tmp/adb.log?보다 일반적으로 일종의 프로세스별 심볼릭 링크를 만드는 방법이 있습니까?/tmp/adb.log모든 파일 액세스를 file 로 리디렉션하고 싶습니다 ~/tmp/adb.log.

다시 말하지만, 저는 서버의 루트가 아니므로 chroot, mount -o rbindchmod는 유효한 옵션이 아닙니다. ADB 소스코드는 가능하다면 수정하고 싶지 않지만, 다른 해결 방법이 없다면 반드시 수정하겠습니다.

PS 특정 ADB 사례의 경우 리디렉션을 실행 adb nodaemon server하고 nohup출력할 수 있지만 일반적인 질문은 여전히 ​​관련이 있습니다.

답변1

LD_PRELOAD는 그다지 어렵지 않으며 루트 권한이 필요하지 않습니다. open()C 라이브러리의 실제 루틴 대신 호출될 고유한 C 루틴을 삽입하십시오 . 루틴은 열려는 파일이 "/tmp/adb.log"인지 확인하고 다른 파일 이름으로 실제 열기를 호출합니다. 이것은 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);
}

컴파일 gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c하고 몇 가지 항목을 넣고 /tmp/myadb.log실행하여 테스트해 보세요 LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log. 그런 다음 adb에서 LD_PRELOAD를 시도해보세요.

답변2

util-linux다음은 를 사용하여 unshare프로세스를 개인 마운트 네임스페이스에 배치하고 현재 상위 프로세스가 소유한 동일한 파일 시스템에 대한 다른 보기를 제공하는 매우 간단한 예입니다 .

{   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

unshare마운트 네임스페이스 기능 자체는 전체 3.x 커널 시리즈에 대해 상당히 성숙했지만 최신 Linux 시스템의 유틸리티를 사용하여 프로세스에 파일 시스템에 대한 비공개 보기를 제공할 수 있습니다. 동일한 패키지에 있는 유틸리티를 사용하여 다양한 기존 네임스페이스를 입력할 수 nsenter있으며 man.

관련 정보