파일이 존재하지 않는다고 생각하도록 프로세스를 속일 수 있습니까?


31

설정을 저장하는 프로그램이 있습니다. ~/.config/myprogram대화식 및 배치 큐잉 시스템과 함께 사용합니다. 대화식으로 실행할 때이 프로그램이 구성 파일을 사용하기를 원합니다. 그러나 배치 모드로 실행할 때는 모든 관련 설정을 덮어 쓰는 명령 줄 옵션을 지정하므로 구성 파일이 필요하지 않습니다. 또한 네트워크를 통해 구성 파일에 액세스하면 프로그램 시작 시간이 몇 초 증가합니다. 파일이 존재하지 않으면 프로그램이 훨씬 빠르게 시작됩니다 (각 작업은 약 1 분 정도 걸리므로 일괄 작업 처리량에 큰 영향을 미칩니다). 그러나 프로그램을 대화식으로 사용하기 때문에 구성 파일을 항상 이동 / 삭제하고 싶지 않습니다. 배치 작업이 클러스터에서 예약되는시기 (다른 사용자의 사용량에 따라)에 따라,

(제외 : 네트워크 파일 성능이 너무 느려 버그 일 가능성이 있지만 아마도 클러스터 사용자 일뿐이므로 해결하지 않고 해결할 수 있습니다.)

배치 사용을 위해 구성 파일을 읽지 않거나 명령 줄 옵션이없는 프로그램 버전을 빌드 할 수 있지만이 프로그램의 빌드 환경은 엔지니어링이 잘못되어 설정하기가 어렵습니다. 시스템의 패키지 관리자를 통해 설치된 바이너리를 사용하는 것이 좋습니다.

이 프로그램의 특정 인스턴스를 구성 파일이 존재하지 않는 것으로 위장하는 방법은 무엇입니까 (프로그램을 수정하지 않고)? 양식의 래퍼를 원 pretendfiledoesntexist ~/.config/myprogram -- myprogram --various-options...하지만 다른 솔루션을 사용할 수 있습니다.


2
파일을 읽을 권한이없는 사용자로 실행할 수 있습니다.
psimon

1
@psimon 클러스터의 "단지 사용자"로서 배치 작업을 실행할 새 사용자를 만들 수 없습니다. 그것은 영리한 아이디어이며 더 나은 제안이 없다면 클러스터 관리자에게 버그를 제기하여 나를 위해 할 것입니다.
Jeffrey Bosboom

또는 먼저 구성 파일의 이름을 바꾸고 프로그램을 실행 한 다음 구성 파일의 이름을 다시 바꾸는 스크립트를 설정하십시오.
psimon

@ psimon 더 명확했을 수 있다고 생각합니다. 배치 작업이 클러스터에서 예약되는 시점에 따라 프로그램을 대화식으로 동시에 배치 모드로 사용하고있을 수 있습니다.
Jeffrey Bosboom

1
예, 동적으로 연결된 경우 LD_PRELOAD후크를 사용할 수 있습니다 . 대안 인 것보다 쉽습니다 (C를 알고 있다면 한두 시간 안에 구현할 수 있습니다) ptrace. 아마도 fakechroot를 사용 하여이 작업을 수행 할 수도 있습니다 (LD_PRELOAD, 나는 믿습니다).
derobert

답변:


33

해당 프로그램은에서 해당 파일의 경로를 확인합니다 $HOME/.config/myprogram. 따라서 홈 디렉토리가 다음과 같은 다른 곳에 있다고 말할 수 있습니다.

HOME=/nowhere your-program

이제 프로그램에 홈 디렉토리에 다른 리소스가 필요할 수 있습니다. 이들이 무엇인지 아는 경우 필요한 리소스에 대한 링크를 통해 프로그램을위한 가짜 집을 준비 할 수 있습니다.

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram

5
이 답변은 내 문제를 해결 하므로이 질문의 제목에있는 질문에 대한 완전한 대답은 아니지만 승인했습니다. 다른 답변에서 설명한 바와 같이 예압 후크는보다 일반적인 (그러나 더 높은 노력) 솔루션입니다.
Jeffrey Bosboom

28

다른 모든 방법이 실패하면 LD_PRELOAD호출을 open("/home/you/my-program/config.interactive")차단하지만 다른 것은 통과 하도록 주입 할 래퍼 라이브러리를 작성하십시오 . 이것은 시스템 호출을 필터링하기 때문에 모든 유형의 프로그램, 심지어 쉘 스크립트에서도 작동합니다.

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

참고 :이 코드를 테스트하지 않았으며 errno부품이 작동 하는지 100 % 확신하지 못합니다 .

방법에 대해 살펴 fakeroot과 같은 호출을 수행 getuid(2)하고 stat(2).

기본적으로 링커는 해당 응용 프로그램을 라이브러리에 연결하여 open심볼 을 재정의합니다 . open자신의 라이브러리에 명명 된 두 개의 다른 함수를 사용할 수 없으므로 두 번째 부분 (예 :)으로 분리해야 합니다. get_real_open그러면 원래 open호출에 연결됩니다 .

기발한: ./Application

Application -----> libc.so
            open()

가로 채기 : LD_PRELOAD=yourlib_wrap.so ./Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

편집 : 분명히 이중 링크에 의지하지 않고 래퍼를 작성할 ld수 있는 플래그를 사용할 수 있습니다 ( --wrap <symbol>).

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}

2

구성 파일을 다른 곳으로 옮기고 파일을 일반 대상으로 복사하고 프로그램을 실행 한 후 종료시 삭제하는 대화식 유스 케이스에 대한 쉘 스크립트 랩퍼를 작성하십시오.


최근 편집 내용보기 : 배치 예약을 제어하지 않으므로 프로그램을 대화식으로 동시에 배치 작업의 일부로 사용하고있을 수 있습니다.
Jeffrey Bosboom

1

unionfs / aufs로 가능해야합니다. chroot프로세스 환경을 만듭니다 . 실제 디렉토리를 읽기 전용 계층으로 사용하고 그 위에 빈 디렉토리를 놓습니다. 그런 다음 unionfs 볼륨을 chroot환경 의 해당 디렉토리에 마운트 하고 파일을 삭제하십시오. 프로세스는 그것을 볼 수 없지만 다른 모든 것들은 볼 수 있습니다.


0

구성 파일 이름을 예를 들어로 바꿉니다 config.interactive. eg라는 다른 빈 파일을 만듭니다 config.script.

이제 config필요한 실제 구성에 대한 소프트 링크 (또는 응용 프로그램이 구성 파일로 기대하는 것)를 만들어 응용 프로그램을 실행하십시오.

ln -s config.interactive config

나중에 링크를 정리하십시오.


최근 편집 내용보기 : 배치 예약을 제어하지 않으므로 프로그램을 대화식으로 동시에 배치 작업의 일부로 사용하고있을 수 있습니다. 이 대답은 본질적으로 파일을 수동으로 또는 스크립트로 이동하는 것과 동일합니다.
Jeffrey Bosboom

1
도! 생각하고 더 빨리 입력해야합니다. 큰 응용 프로그램입니까? chroot로 옮겨서 대화식으로 실행할 수 있습니까? 그것은 모두 프로그램이 상호 작용하는 것에 달려 있다고 생각합니다. 필요한 모든 것을 chroot로 가져 오는 것도 매우 지루한 작업 일 수 있습니다. (나는 그 옵션의 자신을 이야기했다고 생각!)
garethTheRed

0

프로그램이 구성 파일을 사용하는 방식을 정확하게 특성화했다면 간과했습니다. 많은 프로그램 (예 : bashvi)은 시작시 즉시 구성 파일을 확인합니다. 파일이 존재하면 파일을 읽고 닫으십시오. 이러한 프로그램은 이러한 초기화 파일에 다시 액세스하지 않습니다. 프로그램이 그런 경우 계속 읽으십시오.

이름을 바꾸어 구성 파일을 실제로 존재하지 않는 답변을 거부했지만 다른 사람이 제안하지 않은 주름이 있습니다. 배치 모드에서 프로그램을 호출 할 때이를 수행하십시오.

DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"

mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram

이렇게하면 구성 파일이 방해가되지 않지만 myprogram여전히 실행 중이 더라도 1 초 후에 다시 이동합니다 . 이렇게하면 파일을 사용할 수없는 시간이 매우 짧아집니다.이 창에서 대화식으로 프로그램을 실행할 확률은 얼마입니까? (그렇더라도 종료하고 다시 시작하면 구성 파일이 다시 설치 될 수 있습니다.)

이것은 경쟁 조건을 만듭니다. 프로그램이 파일을 여는 데 너무 오래 걸리면 실제 파일을 얻을 수 있습니다. 이것이 자주 문제가되는 경우 DELAY_TIME의 값을 늘리십시오.


1
잘못 될 수있는 최악의 것은 무엇입니까? 나는 그것이 실제로 일어나는 것을 보았습니다. 생산 중.
Henk Langeveld

-1

스테판의 대답처럼 나는,하지만이됩니다 속임수 모든 파일을 믿기로 모든 프로그램은 - (그 dentry가 일시적으로 실제로 비어있는 파일을 가리키는 때문에) :

cat <./test.txt
###OUTPUT###
notempty

mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###

umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty

당신은 또한 할 수 있습니다 :

mount --bind ./someotherconfig.conf ./unwanted.conf

원한다면


이것은 본질적으로 이전의 두 가지 답변과 같습니다 (단, 사용자가 특권을 요구한다는 점을 제외하고). 그 트릭을하지 않기 때문에 영업 이익이 그 다른 답변을 거부 어떤 그가 대화 형 호출이 일반적으로 설정 파일을 참조하십시오시키는 동안, 프로그램의 일괄 호출을 속여 싶어 - 과정을.
Scott

@Scott-나는 동의하지 않습니다-이 전에 모든 다른 대답 mv은 파일 수정 에 대한 약간의 변형을 권장 합니다. 이는 파일 또는 실제로 다른 부분을 잘라내는 등의 치열에 영향을 미치는 것보다 다른 결과를 초래할 수 있습니다. 아직도, 나는 unshare그렇게 mount생각 해야 한다 ...
mikeserv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.