문제

디스크립터가 사용자 정의 가능한 동작을 가진 파일을 만들고 싶습니다. 특히, 작성 될 때 프로세스 이름과 PID (및 시간)의 이름으로 모든 라인을 접두사 할 수있는 파일 디스크립터를 만들고 싶습니다. 그러나 다른 일을하는 것이 유용 할 수 있다고 상상할 수 있습니다.

글쓰기 프로그램을 변경하고 싶지 않습니다. 한 가지 점에서 제 시스템의 모든 프로그램, 심지어 Shell/Perl/등에 작동하기를 원합니다. 스크립트, 그리고 모든 것의 소스 코드를 변경하는 것은 불가능하지 않으면 비현실적입니다.

이 경우 파이프는 작문 과정에서 파이프가 수행되지 않을 것입니다. fork()S, 새로 생성 된 아동은 FD를 공유하며 파이프의 읽기 끝에 의해 부모와 구별 할 수 없습니다.

할 수있는 접근법이 있지만 다소 서투른 것 같습니다.

  1. 이러한 FDS를 생성하는 커널 모듈을 만듭니다. 예를 들어, 일부를 열 수 있습니다 /dev/customfd 그런 다음 모듈에 일부 변환 등을 수행하거나 사용자 공간 또는 소켓 등으로 데이터를 보내도록 지시합니다.
  2. FD 조작 기능을 무시하고 "특별한"FD에서 이러한 종류의 일을 수행하는 LD_PRELOAD를 사용하십시오.

그러나이 두 가지 접근 방식은 매우 힘들기 때문에 더 나은 방법이 있는지 또는 도움이 될 인프라 (등장 라이브러리와 같은)가 있는지 알고 싶습니다.

커널 변경이 포함되지 않는 솔루션을 선호하지만 필요한 경우 수락 할 준비가되었습니다.

그냥 아이디어 : 퓨즈가 답이 될까요?

도움이 되었습니까?

해결책

LD_PRELOAD 랩핑을 사용하여 write ()/read () 함수를 사용하는 것이 좋은 방법입니다.

Unix Ptrace (2)를 사용하여 원하는 시스템 호출을 잡고 인수를 자신의 기능으로 전달하는 것이 좋습니다.

예시 :

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>
#include <sys/syscall.h>   /* For SYS_write etc */
int main()
{   pid_t child;
    long orig_eax, eax;
    long params[3];
    int status;
    int insyscall = 0;
    child = fork();
    if(child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("/bin/ls", "ls", NULL);
    }
    else {
       while(1) {
          wait(&status);
          if(WIFEXITED(status))
              break;
          orig_eax = ptrace(PTRACE_PEEKUSER,
                     child, 4 * ORIG_EAX, NULL);
          if(orig_eax == SYS_write) {
             if(insyscall == 0) {
                /* Syscall entry */
                insyscall = 1;
                params[0] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * EBX,
                                   NULL);
                params[1] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * ECX,
                                   NULL);
                params[2] = ptrace(PTRACE_PEEKUSER,
                                   child, 4 * EDX,
                                   NULL);
                printf("Write called with "
                       "%ld, %ld, %ld\n",
                       params[0], params[1],
                       params[2]);
                }
          else { /* Syscall exit */
                eax = ptrace(PTRACE_PEEKUSER,
                             child, 4 * EAX, NULL);
                    printf("Write returned "
                           "with %ld\n", eax);
                    insyscall = 0;
                }
            }
            ptrace(PTRACE_SYSCALL,
                   child, NULL, NULL);
        }
    }
    return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top