반응형

개발하고 있는 파일 시스템 필터 드라이버 ...


일단 기본기능은 구현했다만,,,이놈 저놈 테스트시마다 문제가 발생한다.

이번에 만난 문제는 Windows2000에서의 구동문제다.

Sfilter
를 기반으로한 드라이버이고, WindowsXP Vista에서는 정상 구동...

Windows 2000의 경우, 이미 로드된 파일시스템 드라이버에 대한 통지를 받지 못한다고 하니,
추가 코드가 필요하려니 하긴 했지만, 예상치 못한 문제가 발생한다.

1. 첫번째 문제 - SLIST ( 이건 파일시스템 필터와 관련된건 아니지만)
드라이버를 설치하고 로드하려고 하니 아래와 같은 메시지를 뱉어내며, 로딩이 안된다.


뭔가 Win2k에서 지원하지 않는 함수를 쓴거 같기는 한데...
네이버에 물어보니 ExFreeToNPagedLookasideList()와 관련이 있단다. 내부적으로 SList관련 함수를 쓰는 모양이다
.

그렇지만 의문이 생기는 것은 Sfilter도 동일한 함수를 사용했지만, Sfilter 드라이버는 win2k에서 로딩이 된다는 거다
..
하나 하나 추적하며 테스트 해보니, 결국 ExFreeToNPagedLookasideList()을 사용한 코드가 문제이긴 했다
.
원인이 뭘까
?

----------------------------------------------------------------------------------------------------
Sfilter
에는 다음의 구문이 존재한다. Win2k에서 SList를 쓰기위한 먼가의 정의 인거 같다.

#ifndef _WIN2K_COMPAT_SLIST_USAGE
#define _WIN2K_COMPAT_SLIST_USAGE
#endif


우선 문제의 해결은 위의 구문을 헤더에 추가해 주거나, Sorces파일에 다음 구문을 추가해 주면 된다.

C_DEFINES=$(C_DEFINES) -D_WIN2K_COMPAT_SLIST_USAGE

그리고 원인을 찾고 나니 눈에 띄는 ExFreeToNPagedLookasideList() 관련 DDK문서의 내용...
On Microsoft Windows 2000, drivers must use the
D_WIN2K_COMPAT_SLIST_USAGE switch to successfully link code that uses ExFreeToPagedLookasideList

그런데.. ExFreeToNPagedLookasideList 도 똑같구만.. ExFreeToNPagedLookasideList
섹션에는 커맨트를 빼먹어서 사람을 혼란스럽게 하냔 말이다
.
(
역시 소스를 참고할때는 꼼꼼해 살펴봐야 손가락이 고생안한다. )


----------------------------------------------------------------------------------------------------
위와 같이 처리하는 이유는 wdm.h에 존재하는 아래의 코드 때문이다.

#if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
NTKERNELAPI
PSLIST_ENTRY
FASTCALL
ExInterlockedPopEntrySList (
__inout PSLIST_HEADER ListHead,
__inout __deref __drv_neverHold(KeSpinLockType) PKSPIN_LOCK Lock
);

NTKERNELAPI
PSLIST_ENTRY
FASTCALL
ExInterlockedPushEntrySList (
__inout PSLIST_HEADER ListHead,
__inout __drv_aliasesMem PSLIST_ENTRY ListEntry,
__inout __deref __drv_neverHold(KeSpinLockType) PKSPIN_LOCK Lock
);

#else

#define ExInterlockedPopEntrySList(ListHead, Lock) \
InterlockedPopEntrySList(ListHead)
#define ExInterlockedPushEntrySList(ListHead, ListEntry, Lock) \
InterlockedPushEntrySList(ListHead, ListEntry)

#endif

* 2011.05.04 추가


2. 두번째 문제 Filter Group
Sfilter
샘플을 보면, 드라이버의 필터 그룹을 "FSFilter Activity Monitor"로 설정한다.
(Windows 2000
에는 "FSFilter Activity Monitor"그룹이 없다던데
....)
MS
에서 만든 샘플이니 일단 따라해 봤다
.
등록도 되고 잘 동작하는듯 보였는데
...
파일 생성/Read/Write 모두 필터링이 안되는 문제가 발생했다
.
확인해 보니 Ntfs드라이버가 생성한 DeviceObject Attach가 안된다
.
Ntfs
파일시스템 등록시 통지를 해주지는 않는 듯 하다
.

필터 그룹을 "Filter"로 해서 등록하니 이제야 정상 동작.

 

규격에 끼워맞춰 코딩하는건 참 지난한 작업인 것 같다.

 

반응형
반응형

IRP_MJ_MAXIMUM_FUNCTION

 

아래에 이어서 파일시스템 필터 드라이버 등록시 발생한 문제.

 

파일 시스템 드라이버로 등록한 후 재 부팅...

이번에는 문제 없겠지...?

 

하지만 이번에도 발생한 애매모호한 문제...

 

재 부팅시 아래와 같은 메시지가 팝업 되는거다.

 

 

뜬금없이 왠 페이징 사이즈??

 

처음에는 드라이버에서 사용하는 전역변수 크기가 너무 큰지?

드라이버 코드가 메모리를 넘 마니 잡아먹는지?

에 초점을 맞춰 봤지만, 이래 저래 코드를 빼봐도 마찬가지 였다.

 

그러던중, 시스템의 페이징 사이즈 정보를 보니 0으로 설정되어 있는게 아닌가?

 

좀 쪽 팔린 얘기지만 이 문제 확인하면서, 윈도우즈가 페이징 처리하는 대상 파일이 Pagefile.sys라는걸 알았다.

 

그렇담... 이놈을 읽거나 쓰는 게 문제가 아닐까?

역시나 디버깅을 해보니, 내가 작성한 드라이버가 C드라이브에 볼륨에 Attach되면 pagefile.sys Create할때 몇 번의 에러가 발생하는 게 아닌가?

 

이번에도 Sfilter와 비교해가며, Attach하는 부분을 싹 다 점검하고, 코드를 하나하나 빼가며 확인하기 시작했다.

 

문제의 원인은??? .

바로 이코드다...

for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )

{

  DriverObject->MajorFunction[i] = DispathPassthru;

}

 

무슨 문제인지 감이 오십니껴????

 

i < IRP_MJ_MAXIMUM_FUNCTION 가 아니라 i <= IRP_MJ_MAXIMUM_FUNCTION 로 작성해야 하는 코드였다.

 

ntddk.h파일을 보면

IRP_MJ_CREATE( 0x00 )에서 시작해서

IRP_MJ_PNP( 0x1b ) 까지 정의가 되어 있다.

그런데 IRP_MJ_MAXIMUM_FUNCTION의 값은 0x1c가 아니라  0x1b인거다.

 

MajorFunction[] 배열을 모두 DispathPassthru로 채워주자면

 i <= IRP_MJ_MAXIMUM_FUNCTION 인경우까지 루프를 돌려줘야 한다.

 

직접적인 연관 관계는 알 수 없지만, IRP_MJ_PNP에 대한 디스패치 함수가 등록되지 않아 발생한 문제로 보여진다.

 

이 문제 확인하는데 1주일이 걸리긴 했지만...

그래도 pagefile.sys에 대한 내용과 DriverObject->MajorFunction[]를 채우는 부분에 대해

머리속 깊이 각인되었으니 그나마 다행...

 

그래도 되도록이면 삽질하지 말자..

 

 

반응형
반응형

Device Naming

 

첫번째 개발 프로젝트인 파일시스템 드라이버...

하나씩 확인해 가며 개발하려니 만만치가 않군...

 

워쨌든 간에 좀 보완해야 할 부분은 있지만, 기본 구조와 기능들은 이래 저래 시행착오를 겪어가며 개발했다.

 

이제 이놈을 드라이버 타입을 파일시스템으로 해서 등록하고, 로드 시점을 시스템 부팅 시 올라오도록 등록만 하는 되는데...

 

역시나, 한번에 되는게 없다..^
드라이버 서비스 등록 시 파일시스템 드라이버 타입으로 등록하니, 잘 돌아가던 드라이버가 로드가 안되는게지...

오류 메시지는... 이미 있는 놈이라 생성을 할 수 없단다...

 

Sfilter 방식으로도 설치해보고, 이래저래 비교를 해봤건만... 미궁....

 

고생 고생해서 확인하고 나니...

Control DeviceObject의 이름문제였다.

 

원래 지정했던 이름은 \\FileSystem\\XXXX

그런데 파일시스템 드라이버 타입으로 등록하면, 드라이버 이름도 \\FileSystem\\XXX로 등록된다는 사실...

 

드라이버 이름과 Control Device 이름이 같아서 발생한 문제였다.

 

* 디바이스 이름 명명시 Device Device간 뿐만 아니라 DeviceDriver 이름 또한 중복된 이름을 만들면 안 된다.

지금 생각하면 당연한 건데 ㅡ.

 

이전 버전 드라이버 개발했던 분이,

작성한 파일 시스템 필터 드라이버의 CDO이름을  \\FileSystem\\XXX로 등록하니 안 되서 \\FileSystem\\XXX0로 했다고 하더니 같은 문제더라. 머 이런 얘기다.

 

반응형
반응형

 

메모리를 할당한 후 반드시 리턴값을 확인 할 것

 

커널 메모리가 소진되어 메모리를 더 이상 할당 할 수 없는 경우가 발생할 가능성이 얼마나 될까?

드라이버 관련 유지보수 및 개발담당한지 7개월 남짓이지만,

간간히 레포트가 들어오는 사항이다.

첫번째로 레포트된 문제는 인계받은 드라이버 쪽에서의 메모리 누수로 인한 메모리 할당 실패...
(
찾느라 애좀 먹었다.. 위대하신 PoolTag님의 도움으로 겨우 해결.)
이 경우야 우리 드라이버의 문제이므로, 변명의 여지 없음이고....

그 외에도 ExAllocatePool() 호출이 실패하여 NULL이 리턴되고,
NULL 포인터에 메모리를 쓰려다가 발생한 BSOD도 심심찬게 레포트 된다.


메모리 할당 후 리턴값을 확인하는 것은 왜 필요한가?

내가 작성한 드라이버가 아닌 다른 드라이버가 커널 메모리를 누수시키며 동작하고 있다고 가정하자.

이 문제의 드라이버 때문에 어느 순간인가 메모리 할당이 실패할 것이고,

그렇게 되면 우리 드라이버는 메모리 할당이 실패한 줄도 모르고 잘못된 메모리를 참조하여,
우리 드라이버가 요주의 용의자로 지목되는 BSOD가 발생할 가능성이 다분하다.

그러면 어찌될지는 뻔한 일이다. 분명 우리 드라이버의 문제가 아님에도 우리 쪽으로 버그 레포트가 올테고 우리 드라이버의 문제가 아님을 증명하기 위해 시간과 노력을 투자할 밖에....

이런 의미에서 메모리 할당후에 정상적으로 할당되었는지 확인하는 것은 아주 기본적이지만 중요한 습관이다.

새로 작성하는 코드 전체에 할당 성공 여부를 확인하는 코드를 삽입하고,
DriverVerifier
Low Resource Simulation 옵션을 를 체크하여 테스트 해보니
BSOD
없이 잘 구동된다.....

다만 이경우, 메모리 할당 실패로 우리의 드라이버가 정상적인 동작을 할 수 없을 가능성이 다분하므로, 이러한 상황을 확인 할 수 있는 별도의 조치가 필요하리라..

 

반응형
반응형

DRIVER_POWER_STATE_FAILURE (9f)


A driver is causing an inconsistent power state.
Arguments:
Arg1: 00000500,
The device object completed the irp for the system power
state request, but failed to call PoStartNextPowerIrp
.
Arg2: 00000002
Arg3: 8188ab80, Optional Target device's DEVICE_OBJECT
Arg4: 81982d98, DeviceObject

Debugging Details:

DRVPOWERSTATE_SUBCODE: 500

DEVICE_OBJECT: 8188ab80

DRIVER_OBJECT: 817c7718

IMAGE_NAME: MyDriver.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 49e3e422

MODULE_NAME: MyDriver

FAULTING_MODULE: f7645000 MyDriver

DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT

BUGCHECK_STR: 0x9F

PROCESS_NAME: System

LAST_CONTROL_TRANSFER: from 804f99f7 to 80528fe8

STACK_TEXT:
f9c1a88c 804f99f7 00000003 f9c1abe8 00000000 nt!RtlpBreakWithStatusInstruction
f9c1a8d8 804fa5e4 00000003 00000000 81982d98 nt!KiBugCheckDebugBreak+0x19
f9c1acb8 804fab0f 0000009f 00000500 00000002 nt!KeBugCheck2+0x574
f9c1acd8 80649fec 0000009f 00000500 00000002 nt!KeBugCheckEx+0x1b
f9c1ad18 8064a413 000724f8 00000000 00000005 nt!PopWaitForSystemPowerIrp+0x3c0
f9c1ad34 8064a704 fb0724f8 fb07268c 8055ac90 nt!PopSleepDeviceList+0xcb
f9c1ad5c 80646e7a 00000000 8055c440 8197d3c8 nt!PopSetDevicesSystemState+0x1a4
f9c1ad74 80536006 00000000 00000000 8197d3c8 nt!PopGracefulShutdown+0x12c
f9c1adac 805c6d5a 00000000 00000000 00000000 nt!ExpWorkerThread+0x100
f9c1addc 805431e2 80535f06 00000000 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16


STACK_COMMAND: kb

FOLLOWUP_NAME: MachineOwner

FAILURE_BUCKET_ID: 0x9F_VRF_IMAGE_MyDriver.sys

BUCKET_ID: 0x9F_VRF_IMAGE_MyDriver.sys

Followup: MachineOwner

파일 RW를 감시하는 파일시스템 필터 드라이버 작성 중 위의 버그체크 코드를 만났다.
CD Burning
을 감시하기 위해, CdRomX Attach한 후 시스템을 재 부팅하거나

종료할 때 발생한 문제이다.

WinDbg
가 분석해준 내용을 살펴보면 power관련된 처리를 제대로 하지 못했다는 내용인데
,
좀 자세히 살펴보자

WinDbg
도움말에서 해당 버그첵 코드를 확인해 보면 파라미터 각각에 대한 설명이 상세히 기술되어 있다.

The following parameters appear on the blue screen. Parameter 1 indicates the type of violation.

Parameter 1

Parameter 2

Parameter 3

Parameter 4

Cause

0x1 (Windows 2000 and later)

The device object

Reserved

Reserved

The device object that is being freed still has an outstanding power request that it has not completed.

0x2 (Windows 2000 and later)

The target device's device object, if it is available

The device object

The driver object, if it is available

The device object completed the I/O request packet (IRP) for the system power state request, but it failed to call PoStartNextPowerIrp.

0x3 (Windows 2000 only)

A pointer to the target device object

Apointer to the device object

The IRP

The device driver did not properly set the IRP as "pending" or complete the IRP.

0x3 (Windows XP and later)

The physical device object (PDO) of the stack

The functional device object (FDO) of the stack

The blocked IRP

A device object has been blocking an IRP for too long a time.

0x100 (Windows 2000 only)

A pointer to the nonpaged device object

A pointer to the target device object

A pointer to the device object to notify

The device objects in the devnode inconsistently used DO_POWER_PAGABLE.

0x101 (Windows 2000 only)

The child device object (FDO)

The child device object (PDO)

The parent device object

A parent device object has detected that a child device has not set the DO_POWER_PAGABLE bit.

0x500 (Windows XP and Windows Server 2003 only)

Reserved

The target device's device object, if available

Device object

The device object completed the IRP for the system power state request, but it failed to call PoStartNextPowerIrp.


A driver is causing an inconsistent power state.
(드라이버가 엉터리 파워상태를 야기했다)
Arguments:
Arg1: 00000500,
The device object completed the irp for the system power
state request, but failed to call PoStartNextPowerIrp
.
(디바이스 오브젝트가 시스템 파워 상태 요청에 대해 irp를 완료하기는 했으나
PoStartNextPowerIrp()
를 호출하는 데 실패했다. 머 이런 내용이다.)
Arg2: 00000002
Arg3: 8188ab80, Optional Target device's DEVICE_OBJECT
(이놈은 우리 드라이버가 irp를 잔달한 우리 드라이버의 하위 드라이버의 포인터 이다.)

Arg4: 81982d98, DeviceObject
(문제를 야기한 이놈은 역시나 우리의 드라이버다.)

파일 시스템 드라이버야 WDM이 아닌 레거시 드라이버이다 보니 IRP_MJ_POWER에 대한 별도 처리부분은 없는 상태이고, CdRomX Attach DeviceObject로 파워관련 IRP가 내려오지 싶다.

역시나 확인을 해보니, 시스템 종료시 CdRomX Attach한 디바이스 ObjectIRP_MJ_POWER IRP가 내려온다
.

사실 작업 대상이 디바이스가 아닌 파일시스템 쪽이다 보니, POWER,PNP관련 된 부분은 크게 신경 쓰지 않았거덩....(자랑이냐
?)

여하간에 WDM 관련 책을 보니 IRP_MJ_POWER 요청에 대해서는 어찌 어찌 하라는 코드가 있더란 말이지
...

그래서 IRP_MJ_POWER IRP를 걸러내서 이렇게 변경했다..

IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( pDevExt->LowerDevObj, Irp );

PoStartNextPowerIrp( Irp );
IoSkipCurrentIrpStackLocation( Irp );
return PoCallDriver( pDevExt->LowerDevObj, Irp );

일단 문제는 사라졌는데... 좀 더 확인이 필요할것 같다.
현재는 특정 Dispatch함수를 모든 IRP의 디스패치 루틴으로 등록하는 방식인데, IRP_MJ_POWER에 대한 디스패치 루틴을 등록하지 않으면 문제가 발생하지 않을까
?

아 그리고, CdRomX Attach할때 Attach대상 디바이스 객체의 Flags DO_POWER_PAGABLE이 설정되어 있으면, 우리의 디바이스 객체에도 DO_POWER_PAGABLE를 설정해 주어야 한단다
.

추측이 다소 포함된 내용이므로 전적으로 신뢰하지 말것
...
책임질 수 없음.

 

반응형
반응형
WinDbg Vista에서 디버그 프린트 출력하기

출처: http://greemate.tistory.com/81

greemate님의 홈페이지 에서 가져왔습니다.

VISTA 에서 디버그 메시지가 기본적으로 꺼져 있다는 것 알고 계시지요?
Windows Server 2008 도 마찬가지구요.

까먹구 있었는데 디버깅하다가 보니 DbgPrint/KdPrint 로 출력한 디버그 메시지가 안나오더라구요.
어떻게 켜는지 확인해 보니 WinDbg 명령창에서 아래와 같이 Kd_DEFAULT_MASK 를 수정하면 되더군요.
다음 번에 또 찾기 귀찮아서 여기에 적어 둡니다.

* DPFLTR_INFO_LEVEL 로 켜고 싶을 때
kd > ed Kd_DEFAULT_MASK 8

* DPFLTR_ERROR_LEVEL 로 켜고 싶을 때
kd > ed Kd_DEFAULT_MASK 0xF

* 디버그 메시지를 끄고 싶을 때
kd > ed Kd_DEFAULT_MASK 0

8 로 해도 제가 DbgPrint 한 메시지들은 모두 나오더군요.
참고하시기 바랍니다.

자세한 내용은 아래 링크에 있습니다.
http://www.osronline.com/article.cfm?article=295


http://www.driveronline.org/bbs/view.asp?tb=tipbbs&GotoPage=1&s_bulu=&s_key=&no=101
반응형

+ Recent posts