Share via


썽킹이 필요한 이유

커널 모드 드라이버는 사용자 모드 애플리케이션에서 전달된 모든 I/O 버퍼의 크기를 확인해야 합니다. 32비트 애플리케이션이 포인터 정밀도 데이터 형식이 포함된 버퍼를 64비트 드라이버에 전달하고 썽킹이 발생하지 않는 경우 드라이버는 버퍼가 실제로보다 클 것으로 예상합니다. 포인터 정밀도는 32비트 Microsoft Windows에서 32비트, 64비트 Windows에서는 64비트이기 때문입니다. 예를 들어 다음 구조 정의를 고려합니다.

typedef struct _DRIVER_DATA
{
    HANDLE           Event;
    UNICODE_STRING   ObjectName;
} DRIVER_DATA;

32비트 Windows에서 DRIVER_DATA 구조체의 크기는 12바이트입니다. 다음 표에서는 DRIVER_DATA 구조체의 Event 멤버 및 ObjectName 멤버의 크기를 보여 줍니다.

이벤트 ObjectName(USHORT 길이) ObjectName(USHORT 최대 길이) ObjectName(PWSTR 버퍼)
32비트 16비트 16비트 32비트
(4바이트) (2바이트) (2바이트) (4바이트)

64비트 Windows에서 DRIVER_DATA 구조체의 크기는 24바이트입니다. 버 멤버를 8바이트 경계에 맞출 수 있도록 4바이트 구조 패딩이 필요합니다.

이벤트 ObjectName(USHORT 길이) ObjectName(USHORT 최대 길이) 비어 있음(구조 패딩) ObjectName(PWSTR 버퍼)
64비트 16비트 16비트 32비트 64비트
(8바이트) (2바이트) (2바이트) (4바이트) (8바이트)

64비트 드라이버가 24바이트를 예상할 때 12바이트의 DRIVER_DATA 받으면 크기 유효성 검사가 실패합니다. 이를 방지하려면 드라이버는 DRIVER_DATA 구조가 32비트 애플리케이션에서 전송되었는지 여부를 감지해야 하며, 이 경우 유효성 검사를 수행하기 전에 적절하게 썽크해야 합니다.

예를 들어 위의 DRIVER_DATA 구조체의 썽크된 버전은 다음과 같이 정의할 수 있습니다.

typedef struct _DRIVER_DATA32
{
    VOID *POINTER_32   Event;
    UNICODE_STRING32   ObjectName;
} DRIVER_DATA32;

고정 정밀도 데이터 형식만 포함하기 때문에 이 새로운 구조는 32비트 Windows 및 64비트 Windows에서 동일한 크기입니다.

이벤트 ObjectName(USHORT 길이) ObjectName(USHORT 최대 길이) ULONG 버퍼
32비트 16비트 16비트 32비트
(4바이트) (2바이트) (2바이트) (4바이트)