동일한 "열린 파일 설명"을 공유하는 파일 설명자 찾기


17

내가 (본과 같은 껍질에서) 할 경우 :

exec 3> file 4>&3 5> file 6>> file

파일 설명자 3과 4는 4가 dup()3에서 시작되었으므로 동일한 열린 파일 설명 (동일한 속성, 파일 내에서 동일한 오프셋 ...)을 공유합니다. 해당 프로세스의 파일 디스크립터 5와 6은 다른 열린 파일 설명 에 있지만 (예를 들어 파일에 고유 한 포인터가 있습니다).

이제 lsof출력 결과는 다음과 같습니다.

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

다음과 lsof +fg같이 조금 나아졌습니다 .

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(여기서는 Linux 3.16에서) fd 6에는 다른 플래그가 있으므로 fd 3, 4 또는 5의 파일 과 다른 열린 파일 설명 이어야 하지만 fd 5가 다른 열린 파일 설명 . 를 사용하면 -o오프셋도 볼 수 있지만 동일한 오프셋이 동일한 열린 파일 설명을 보장하지는 않습니다 .

방해하지 않는 1 가지 방법이 있습니까? 외부 또는 프로세스 자체 파일 설명자?


1 . 휴리스틱 접근법 중 하나는 fd의 플래그를 변경하고 fcntl()다른 파일 디스크립터가 플래그를 업데이트 한 결과를 보는 것이 될 수 있지만, 이상적이지 않고 어리석은 증거는 아닙니다.


이 접근법은 원칙적으로 작동하며 대부분의 시나리오에서 너무 혼란스럽지 않아야합니다. 먼저 아이를 포크하십시오 (외부에서 수행하는 경우 ptrace 사용). 그런 다음 자식에서 다른 프로세스에 영향을 미치지 않는 파일 설명자를 사용하여 작업을 수행하십시오. Linux에서는 임대가 작동합니다.
Gilles 'SO- 악마 중지

@ Gilles, 고맙지 만 이미 질문에서 제안한 접근법입니다. 임대 (F_SETLEASE fcntl을 의미한다고 가정하면 BTW를 알고 있기 때문에 감사합니다)는 소유 한 일반 파일 에서만 작동 하며 동일한 파일 (EBUSY)에 다른 "쓰기" 열린 파일 설명 이있는 경우 에만 작동 하지 않습니다. 방해하지 않습니다.
Stéphane Chazelas

이 질문을 포기 했습니까? SystemTap이 원하는 작업을 수행하는 방법에 대한 정보를 게시했지만 답변을 완료로 표시하지 않았습니다 ...?
Azhrei

답변:


2

Linux 3.5 이상에서는 kcmp (3) 으로 수행 할 수 있습니다 .

KCMP_FILE

  • 파일 디스크립터 있는지 확인 IDX1 공정에서 PID1이 같은 열린 파일 정보를 말한다 (참조 열기 (2) 와 같은 파일 설명자) idx2 공정에서 PID2를 . 동일한 열린 파일 설명을 참조하는 두 개의 파일 디스크립터가 존재하면 dup (2) (및 유사한) fork (2) 또는 도메인 소켓을 통해 파일 디스크립터를 전달 하여 발생할 수 있습니다 ( unix (7) 참조 ).

매뉴얼 페이지는 OP가 요청한 유스 케이스에 대한 예제를 제공합니다. 이 syscall을 사용하려면 커널을 CONFIG_CHECKPOINT_RESTOREset 로 컴파일해야합니다 .


감사. 정확히 내가 찾던 것. 수퍼 유저가 아니라면 두 가지 프로세스가 있어야합니다 (그리고 setuid / setgid가 아님).
Stéphane Chazelas

@StephaneChazelas 정확합니다. 어떤 이유로 CPIU 지원이 커널에 내장되어 있지 않고 다시 빌드하지 않으려는 경우 struct file *포인터 를 비교할 수있는 일부 사용자 인터페이스를 내보내는 커널 모듈을 항상 작성할 수 있다고 가정합니다 .
minmaxavg

3

비교하고자 struct file하는 것은 파일 설명자가 가리키는 포인터입니다. (내부 커널은 하나 개이며 task_struct그것은라는 또 다른 구조에 대한 포인터를 포함합니다. 각 스레드에 대한 데이터 구조 files_struct. 그리고 구조는 포인터의 배열하는 각 하나를 포함 struct file. 그것은의 struct file오프셋 추구, 오픈 플래그 및을 보관 유지하는 다른 필드는 거의 없습니다.)

files_struct침입 도구를 사용하는 것 이외의 다른 방법으로 포인터를 볼 수있는 사용자가 볼 수있는 방법을 모르겠습니다 . 예를 들어, SystemTap에 PID가 주어지면 해당하는 것을 찾고 task_struct포인터를 따라갈 수 있습니다. 그러나 수동적 인 것을 찾고 있다면 그것에 관한 것이라고 생각합니다. Dell은 오래 전에 KME (Kernel Memory Editor)라는 도구를 발표하여 라이브 커널 메모리에 스프레드 시트와 같은 인터페이스를 제공하여 원하는 작업을 수행 할 수 있었지만 64 비트로 이식되지는 않았습니다. (나는 시도했지만 완전히 작동하지 않았으며 왜 그런지 확신하지 못했습니다.)

당신이 lsof도움 이되지 않는 한 가지 이유 는 그 포인터도 보이지 않기 때문입니다 (그러나 +f비 리눅스 시스템 의 옵션을 보십시오 ). 이론적으로의 모든 필드를 비교 struct file하고 두 구조가 동일하다고 생각할 수 있지만 여전히 별도의 open(2)호출 에서 온 것일 수 있습니다 .

아이디어를 얻으려면 pfiles SystemTap 스크립트를 살펴보십시오 . 주소를 인쇄하도록 수정 한 경우 struct file해결책이 있습니다. open_file_by_pid.stp 도 검사 할 수 있는 함수가 있으므로 확인할 수도 있습니다 files_struct. struct file객체를 보고있는 파일 디스크립터 테이블

내가 뭘 하려는지 물어봐도 될까요?


내가 필요한 바로 그 사건을 기억할 수 없다는 것을 인정해야한다. 일부 디버깅 또는 법의학 작업은 의심의 여지가 없습니다.
Stéphane Chazelas

나는 PoC 시스템 탭 코드를 기대하고있다 :-)
Stéphane Chazelas

질문을 게시하기 전에 systemtap 또는 / proc / kcore 접근 방식을 살펴 보았습니다. 어려운 부분은 모든 작업의 ​​모든 fd 대한 정보를 얻는 것이 었습니다 . 내가 찾은 가장 무시할만한 접근 방식은 / proc / * / task / fd 디렉토리의 내용을 생성하는 함수에 연결하는 것이었지만 소스 파일의 특정 행 번호에 연결하는 것과 관련하여 수행 할 수있는 유일한 작업은 아닙니다. 한 커널 버전에서 다음 커널 버전으로 이식 가능합니다. systemtap에서 작업 목록을 실제로 반복 할 수는 없습니다. 아마도 / proc / kcore를 통해 가능하지만 너무 많은 노력과 신뢰할 수없는 것입니다.
Stéphane Chazelas

지금까지 최고의 답변을 주셔서 감사합니다. 나는 당신의 포인터를 살펴볼 것입니다.
Stéphane Chazelas 8:14에

물론 넌 할 수있어! probe begin블록을 설정 for_each_process하고 스크립트에 포함 된 C 코드 블록 에서 매크로를 사용하도록하십시오 ( C 코드를 포함하려면 "guru"모드 SystemTap을 사용해야합니다). 사실, 이것을 흥미롭게 만들기 위해 (!) SystemTap의 연관 배열 중 하나를 사용할 수 있습니다. files_struct주소를 키로 사용하고 PID / TID 목록을 값으로 사용하십시오. 이제 열려있는 모든 파일과 파일을 공유하는 작업 목록이 있습니다 (부모 / 자식간에 공유 가능). SystemTap에 대해 토론하고 싶으면 다시 답장하십시오.
Azhrei

0

리눅스 전용 솔루션은 다음과 같습니다. / proc / self / fd는 현재 프로세스에서 열린 파일 핸들을위한 심볼릭 링크 디렉토리입니다. 링크 값만 비교하면됩니다. 자식 프로세스를 사용할 때 자식이 다른 / proc / self를 가질 수 있기 때문에 자식 프로세스를 사용할 때 더 복잡해집니다. / proc / $$ / fd를 사용하여이 문제를 해결할 수 있습니다. 여기서 $$는 원하는 pid입니다.


감사. 그러나 그것은 내가 요구하는 것이 아닙니다. Linux에서 lsof는 실제로 / proc / pid / fd를 사용하여 각 파일 디스크립터의 경로를 검색하고 / proc / pid / fdinfo를 플래그로 검색합니다. 그러나 내가 원하는 것은 동일한 열린 파일 설명 을 가리키는 지 또는 두 파일 설명자가 독립적으로 열려 있는지 여부에 관계없이 동일한 파일에 대한 두 개의 fd에 대한 것입니다.
Stéphane Chazelas

좋아, 같은 파일 이름으로 열려있는 파일 설명자 쌍을 찾은 후 두 가지에 대해 말하고 결과가 다른 경우 비교하십시오. 동일한 경우 하나의 파일 디스크립터를 탐색하고 반복하십시오. 여전히 일치하면 동일합니다.
hildred

글쎄, 그것은 내가 질문에서 언급하는 휴리스틱 접근법의보다 관입적인 변형이며 소켓, 장치 (터미널과 같은), 파이프 ...가 아닌 일반 파일에서만 작동합니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.