Share event by handle between user and kernel thread

Hi all,

First, I know share event between user and kernel is not safe.
But under some reason, I use this mechanism.

Following is my code:
In kernel mode is a scsi driver
main thread:

case myioctl :
{
VDShrEventHandle_test = *(HANDLE *)OsrSpGetSrbDataAddress(pIInfo->SPLocalHandle,PSrb);
__try {
status = ObReferenceObjectByHandle(VDShrEventHandle_test , GENERIC_ALL, *ExEventObjectType, KernelMode, (PVOID *)(&VDShrEvent), NULL);

if(status == STATUS_SUCCESS)
{
KeSetEvent(&pIInfo->testEvent,KPRIORITY(0),FALSE);
}
} __except(EXCEPTION_EXECUTE_HANDLER) {

status = GetExceptionCode();

}
status = STATUS_SUCCESS;
PSrb->SrbStatus = STATUS_SUCCESS;
}

another thread:

KeWaitForSingleObject( &pLocalInfo->testEvent, Executive, KernelMode, FALSE, NULL );
while(TRUE)
{
if (pLocalInfo->device_close==TRUE)
{
PsTerminateSystemThread(STATUS_SUCCESS);
}
KeWaitForSingleObject(VDShrEvent, Executive, KernelMode, FALSE, NULL );
KeClearEvent(VDShrEvent);
break;
}
KeWaitForSingleObject( &pLocalInfo->testEvent, Executive, KernelMode, FALSE, NULL );
while(TRUE)
{
if (pLocalInfo->device_close==TRUE)
{
PsTerminateSystemThread(STATUS_SUCCESS);
}
KeWaitForSingleObject(VDShrEvent, Executive, KernelMode, FALSE, NULL );
KeClearEvent(VDShrEvent);
KdPrint((“Get share evnt”));
break;
}

In user mode is an user application:
share_event1 = CreateEvent(NULL,FALSE,FALSE,L"Global\NTProcDrvProcessEvent");

ZeroMemory(buffer_handle,4);
CopyMemory(buffer_handle, &share_event1, sizeof(HANDLE));
ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
sptdwb.sptd.PathId = 0;
sptdwb.sptd.TargetId = 0;
sptdwb.sptd.Lun = 0;
sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
sptdwb.sptd.SenseInfoLength = SPT_SENSE_LENGTH;
sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
sptdwb.sptd.DataTransferLength = 4;
sptdwb.sptd.TimeOutValue = 2;
sptdwb.sptd.DataBuffer = buffer_handle;
sptdwb.sptd.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
sptdwb.sptd.Cdb[0] = myioctl;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
status = DeviceIoControl(hUDisk,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
&sptdwb,
length,
&sptdwb,
length,
&bytesReturn,
NULL);
if (0 == iRet)
{
//getlasterror() will return ERROR_IO_DEVICE,but the buffer_handle has been send down to driver successfully.
}
getc();
SetEvent(share_event1);

then the driver receive share event successfully.

Here are two problem:
When I call DeviceIoControl, it would return ERROR_IO_DEVICE,and cause an exception

Break instruction exception - code 80000003 (first chance)
001b:00304036 cc int 3

But after I ignored this exception,BSOD didn’t happen,and windows still works.
Why?And how to solve this problem?

Thanks for any reply.

  1. You MUST use UserMode in ObReferenceObjectByHandle call.
  2. You MUST call ObDereferenceObject after you’re done with it.
  3. You MUST NOT name the event if you don’t want an unique object opened by name.

You need to convert the handle to the object in the context of the application, not your own driver thread . Don’t use SEH either, you are just masking over your own bugs. None of the APIs you are calling have an exception being thrown as a part of their calling contract

d

debt from my phone


From: xxxxx@broadcom.com
Sent: 6/17/2012 8:45 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Share event by handle between user and kernel thread

  1. You MUST use UserMode in ObReferenceObjectByHandle call.
  2. You MUST call ObDereferenceObject after you’re done with it.
  3. You MUST NOT name the event if you don’t want an unique object opened by name.

NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> First, I know share event between user and kernel is not safe.

It is safe, just not convinient for most tasks.

Do not forget to save the PKEVENT somewhere in your devext, and then ObDereferenceObject it at devext destruction.

Also ObReferenceObjectByHandle has no need in a try/except block.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>1. You MUST use UserMode in ObReferenceObjectByHandle call.

  1. You MUST call ObDereferenceObject after you’re done with it.
  2. You MUST NOT name the event if you don’t want an unique object opened by name.
    Thanks for your recommend.
    I find out a sample code that same as what you said in this web site.

After modified, the error “ERROR_IO_DEVICE” cause in user mode deviceiocontrol is dismissed.
However,the exception after KeSetEvent is still there.

You need to convert the handle to the object in the context of the application,
not your own driver thread . Don’t use SEH either, you are just masking over
your own bugs. None of the APIs you are calling have an exception being thrown
as a part of their calling contract
Thanks for your suggestion.
How to convert handle to object in user mode?

It is safe, just not convinient for most tasks.
Do not forget to save the PKEVENT somewhere in your devext, and then
ObDereferenceObject it at devext destruction.
Also ObReferenceObjectByHandle has no need in a try/except block.
Thanks for your suggestion…

> From: xxxxx@lists.osr.com [mailto:bounce-506023-

xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Subject: RE:[ntdev] Share event by handle between user and kernel
thread

After modified, the error “ERROR_IO_DEVICE” cause in user mode
deviceiocontrol is dismissed.
However,the exception after KeSetEvent is still there.

Well, I hope you do see that you are calling KeSetEvent not on shared
event you received from application, but on some other event - your own
internal pIInfo->testEvent. Have you initialized it?

>You need to convert the handle to the object in the context of the
application,
>not your own driver thread .

How to convert handle to object in user mode?

Not in user mode - but in the context of calling application. Since it
seems you are doing it in your ioctl routine, you are in proper context.

Best regards,
Alex Krol

> How to convert handle to object in user mode?

You cannot. User mode does not know about kernel objects. It only know the handles.

There was ZwQuerySystemInformation(SystemHandleTableInformation) or such, which can provide the user mode with the pointer values of the kernel objects. But, in user mode, these values cannot be used as pointers, only as some unique IDs. You cannot access these objects without a handle.

I think “netstat -o” which prints processes owning the sockets uses this stuff. The analogous UNIX tools are using the same technique, just using /dev/kmem or /proc instead of ZwQuerySystemInformation.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>> After modified, the error “ERROR_IO_DEVICE” cause in user mode

> deviceiocontrol is dismissed.
> However,the exception after KeSetEvent is still there.
>

Well, I hope you do see that you are calling KeSetEvent not on shared
event you received from application, but on some other event - your own
internal pIInfo->testEvent. Have you initialized it?

Yes,I have initialized it since initialize device.
I think exception caused between setEvent(testEvent) and WaitForSingleObject (testEvent)
And other possible?

>>You need to convert the handle to the object in the context of the
> application,
> >not your own driver thread .
>
> How to convert handle to object in user mode?
>
>Not in user mode - but in the context of calling application. Since it
seems you are doing it in your ioctl routine, you are in proper context.

Thank you, after this modification,my driver is work.