본문 바로가기

My Study/Programming&Theory

FltCancelFileOpen 궁금증

VOID FltCancelFileOpen(

  _In_  PFLT_INSTANCE Instance,

  _In_  PFILE_OBJECT FileObject

);


이 함수는 새롭게 열린 또는 생성된 파일에 대해 미니필터 드라이버에서 FltCancelFileOpen 함수를 사용해 열기 또는 생성을 취소시키는 함수입니다.


사실 이 함수의 설명을 제대로 읽어보지 못하고 마구잡이로 코딩을 하다가 의문이 들었습니다. 이 함수 설명을 보기전에 전 FltCancelFileOpen 함수를 pre-create 콜백 루틴에서 사용했었습니다. 하지만 MSDN엔 다음과 같은 설명이 되어 있더군요.


FltCancelFileOpen can only be called from a minifilter driver's post-create callback routine. Calling FltCancelFileOpen from a postoperation callback (PFLT_POST_OPERATION_CALLBACK) routine for any other type of I/O operation, or calling it from a preoperation callback (PFLT_PRE_OPERATION_CALLBACK) routine, is a programming error.


FltCancelFileOpen 은 미니필터 드라이버의 post-create 콜백 루틴에서만 호출될 수 있다고 나와있습니다. pre-create 루틴에서 호출하면 이는 프로그래밍 에러라고 하네요. 그러면 전 pre-create 콜백 루틴에서 이 함수를 사용했으니 프로그래밍 에러 였던걸까요?.. 파일 접근 제어를 위해 미니필터를 만들어서 pre 콜백 루틴에 FltCancelFileOpen 를 넣고 사용했는데 잘만 됩니다.


사실 제가 이렇게 코딩했었던 이유는 레거시 파일 시스템 필터 드라이버를 만들 당시 파일에 대한 접근을 막기위해 pre-create 루틴에서 막았기 때문입니다. 완료루틴(post)에서 막지 않았으니 pre-create는 맞겠지요. MSDN에도 나와 있는데 미니필터 드라이버의 pre 작업 루틴은 레거시 필터 모델의 디스패치 루틴과 비슷하다고 하네요. 맞는말 :D


그러면 이걸 똑같이 적용하면 미니필터 드라이버에서도 pre-create에서 막아도 별 문제가 안되는 걸로 생각했습니다.

FltCancelFileOpen 함수를 사용하고 pre-create 콜백 루틴 인자로 들어온 PFLT_CALLBACK_DATA 구조체 값에


PFLT_CALLBACK_DATA->IoStatus.Status = STATUS_ACCESS_DENIED;

PFLT_CALLBACK_DATA->IoStatus.Information = 0;


이렇게 설정 후 FLT_PREOP_COMPLETE 를 리턴했습니다.

pre-create 루틴에서 FLT_PREOP_COMPLETE 를 리턴했다는 것은 해당 미니필터 드라이버에서 I/O 작업을 완료하겠다는 것이고 필터 매니저는 I/O 작업을 디바이스 스택에 아래 있는 어떠한 미니필터 드라이버에게 보내지 않고 파일 시스템에게도 보내지 않습니다. 그래도 디바이스 스택의 위쪽에 있는 드라이버들의 post 작업 콜백 루틴을 호출하겠지요. 아무튼 중요한건 해당 I/O 가 더이상 파일 시스템에 가지 않는 다는 것이므로 당연히 파일 열기 또는 생성이 실패하는 것은 맞습니다.


그런데 .. 왜 post-create 에서만 사용하라고 하는걸까요?... 결국 남은건 IRQL 문제

MSDN에 또 간략히 설명이 되어 있습니다.


Callers of FltCancelFileOpen must be running at IRQL PASSIVE_LEVEL. However, it is safe for minifilter drivers to call this routine from a post-create callback routine, because post-create callback routines are guaranteed to be called at IRQL PASSIVE_LEVEL, in the context of the thread that originated the IRP_MJ_CREATE request.


FltCancelFileOpen 시에는 반드시 IRQL이 PASSIVE_LEVEL에서 작동하도록 되어 있습니다. 그런데 post-create 콜백 루틴 IRP_MJ_CREATE 요청이 시작된 스레드의 컨텍스트에선 IRQL이 PASSIVE_LEVEL이 보장된다네요.


그러면 pre-create는? 특정 I/O 경로에 따라 IRQL이 달라진다네요. 뭔소리?;;

컨텍스트 관련된 이야기는 없네요.


그러면.. post는 I/O 요청한 스레드의 컨텍스트만 맞으면 되는 거고

pre는 I/O 경로에 따라 달라진다는것..그러면 특정 스레드 컨텍스트가 맞아도 I/O 경로에 따라 IRQL이 PASSIVE_LEVEL이 아닐 수도 있다는 말인데요. 음.............=_=;;


모르겠습니다. 이걸 테스트 해보려고 미니필터를 로드시켜 pre와 post 각각의 콜백루틴에 들어왔을 때 IRQL을 2시간 동안 체크를 해보았지만 둘다 PASSIVE_LEVEL이 아니었던적이 없습니다. 한번이라도 pre 루틴에서 IRQL이 0 이 아닌 값이 나오면 좋으려만.. ㅠ


무튼 MSDN에서는 FltCancelFileOpen 을 post 콜백 루틴에서 사용하라니 파일 접근 제어 같은건 post 루틴에서 하는게 맞겠군요. 미니필터 드라이버 샘플 코드를 봐도 post 루틴에서 접근을 막고있구요. 일단 MS 규칙이니 따르래서 따르겠는데 왜왜왜! 

pre 루틴에서 사용하지 말라는지..


pre-create 콜백 루틴에서 IRQL이 0(PASSIVE_LEVEL) 이 아닌 경우의 예 만이라도 알고 싶습니다. 부디 저에게 가르침을..

 ㅠ ㅠ..

'My Study > Programming&Theory' 카테고리의 다른 글

ObRegisterCallbacks 사용해보기  (2) 2012.12.27
Red-Black Tree - 3  (1) 2012.12.24
Red-Black Tree - 2  (0) 2012.12.19
미니필터 드라이버 무력화  (6) 2012.12.12
Red-Black Tree - 1  (0) 2012.12.10