프로세스가 동일한 파일 이름을 가진 다른 파일을 읽도록 합니다.

프로세스가 동일한 파일 이름을 가진 다른 파일을 읽도록 합니다.

파일을 읽는 응용 프로그램이 있습니다. 그렇게 부르자프로세스 이름및 파일~/.구성. 언제프로세스 이름실행하면 항상 읽습니다.~/.구성그리고 다르게 구성할 수 없습니다. 이전과 이후에 "~/.configuration"에 의존하는 다른 애플리케이션이 있지만 이후에는 그렇지 않습니다.프로세스 이름달리기.

패키지프로세스 이름콘텐츠를 대체하는 스크립트에서~/.구성옵션이지만 최근에 정전(내용이 교체되었을 때)이 발생하여 파일의 이전 내용이 손실되었으므로 권장되지 않습니다.

LD_DEBUG=files processname특정 파일을 읽으려고 할 때 프로세스가 다른 것을 읽도록 속이는 방법(아마도 관련성이 높은 것을 사용하는 것일 수도 있음)이 있습니까 ? 실행 파일 내에서 파일 이름을 검색하고 바꾸는 것은 다소 침해적이지만 작동할 것입니다.

호출을 인계받기 위해 커널 모듈을 작성하는 것이 가능하다는 것을 알고 있습니다 open()(https://news.ycombinator.com/item?id=2972958), 하지만 더 쉽고 깔끔한 방법이 있나요?

편집: 검색할 때~/.구성내부에프로세스 이름실행 파일을 읽기 전에 다른 파일 이름을 읽으려고 시도하는 것을 발견했습니다.~/.구성. 문제가 해결되었습니다.

답변1

최신 버전의 Linux에서는 다음을 수행할 수 있습니다.공유 취소이것마운트 네임스페이스. 즉, 가상 파일 시스템을 다르게 보는 프로세스(다르게 마운트된 파일 시스템)를 시작할 수 있습니다.

이는 를 통해 수행할 수도 있지만 chroot귀하 unshare의 경우에 더 적합합니다.

마찬가지로 네임스페이스를 마운트하려면 수퍼유저 권한이 chroot필요합니다 .unshare

~/.configuration그래서, 당신 이 파일을 가지고 있다고 가정 해 봅시다 ~/.configuration-for-that-cmd.

실제로 바인드 마운트인 프로세스를 시작하고 실행할 수 ~/.configuration있습니다 ~/.configuration-for-that-cmd.that-cmd

좋다:

sudo unshare -m sh -c "
   mount --bind '$HOME/.configuration-for-that-cmd' \
                '$HOME/.configuration' &&
     exec that-cmd"

that-cmd모든 하위 프로세스는 서로 다르게 표시됩니다 ~/.configuration.

that-cmd위의 내용은 다음과 같이 실행됩니다 root. sudo -u another-user that-cmd필요한 경우 다음과 같이 실행됩니다.다른 사용자.

답변2

소프트링크.

두 개의 구성 파일을 생성하고 대부분의 경우 소프트 링크를 사용하여 하나를 가리키지만 특수 응용 프로그램이 실행 중인 경우 다른 파일을 가리키도록 소프트 링크를 변경합니다.

(이것이 끔찍한 해킹이라는 것을 알고 있지만 파일 내용을 변경하는 것보다 약간 더 안정적입니다.)

또는 $HOME을 조작하십시오.

귀찮은 프로세스를 시작하는 스크립트에서 $HOME을 일반 $HOME 디렉토리 아래의 항목으로 설정하면 애플리케이션은 해당 위치에 있는 구성 파일을 사용해야 합니다(기본 쉘 명령과 작동하도록 테스트되었으며 ~는 $HOME으로 확장됩니다).

프로세스가 수행하는 다른 작업에 따라 $HOME을 변경하면 의도하지 않은 결과가 발생할 수 있습니다(즉, 출력 파일이 잘못된 위치에 있을 수 있음).

답변3

다음을 사용하여 이 작업을 수행할 수 있습니다.LD_PRELOAD 기술. 이는 특정 접두사로 시작하는 경로를 다른 위치에 매핑하는 구현입니다. 코드는github에도 있어요.

예를 들어, /etc/루트가 되지 않고도 파일 존재를 위조할 수 있습니다. 이는 /etc/ownCloud/sync-exclude.list파일이 존재하지 않을 때 작동을 거부하는 owncloud 클라이언트에 필요합니다 .

이는 한 디렉터리를 다른 디렉터리로 매핑하는 기능을 open()재정 의하여 작동합니다( 예 : .open64()open()/etc/ownCloud/.../home/user1/.etc/ownCloud/...

을 조정한 path_map다음 미리 로드된 lib를 사용하여 프로그램을 컴파일하고 실행하십시오.

gcc -std=c99 -Wall -shared -fPIC path-mapping.c -o path-mapping.so -ldl

LD_PRELOAD=/path/to/my/path-mapping.so someprogram

소스 코드 path-mapping.c:

#define _GNU_SOURCE

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <malloc.h>

// List of path pairs. Paths beginning with the first item will be
// translated by replacing the matching part with the second item.
static const char *path_map[][2] = {
    { "/etc/ownCloud/", "/home/user1/.etc/ownCloud/" },
};

__thread char *buffer = NULL;
__thread int buffer_size = -1;

typedef FILE* (*orig_fopen_func_type)(const char *path, const char *mode);
typedef int (*orig_open_func_type)(const char *pathname, int flags, ...);

static int starts_with(const char *str, const char *prefix) {
    return (strncmp(prefix, str, strlen(prefix)) == 0);
}

static char *get_buffer(int min_size) {
    int step = 63;
    if (min_size < 1) {
        min_size = 1;
    }
    if (min_size > buffer_size) {
        if (buffer != NULL) {
            free(buffer);
            buffer = NULL;
            buffer_size = -1;
        }
        buffer = malloc(min_size + step);
        if (buffer != NULL) {
            buffer_size = min_size + step;
        }
    }
    return buffer;
}

static const char *fix_path(const char *path)
{
    int count = (sizeof path_map) / (sizeof *path_map); // Array length
    for (int i = 0; i < count; i++) {
        const char *prefix = path_map[i][0];
        const char *replace = path_map[i][1];
        if (starts_with(path, prefix)) {
            const char *rest = path + strlen(prefix);
            char *new_path = get_buffer(strlen(path) + strlen(replace) - strlen(prefix));
            strcpy(new_path, replace);
            strcat(new_path, rest);
            printf("Mapped Path: %s  ==>  %s\n", path, new_path);
            return new_path;
        }
    }
    return path;
}


int open(const char *pathname, int flags, ...)
{
    const char *new_path = fix_path(pathname);

    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open");

    // If O_CREAT is used to create a file, the file access mode must be given.
    if (flags & O_CREAT) {
        va_list args;
        va_start(args, flags);
        int mode = va_arg(args, int);
        va_end(args);
        return orig_func(new_path, flags, mode);
    } else {
        return orig_func(new_path, flags);
    }
}

int open64(const char *pathname, int flags, ...)
{
    const char *new_path = fix_path(pathname);

    orig_open_func_type orig_func;
    orig_func = (orig_open_func_type)dlsym(RTLD_NEXT, "open64");

    // If O_CREAT is used to create a file, the file access mode must be given.
    if (flags & O_CREAT) {
        va_list args;
        va_start(args, flags);
        int mode = va_arg(args, int);
        va_end(args);
        return orig_func(new_path, flags, mode);
    } else {
        return orig_func(new_path, flags);
    }
}

관련 정보