[PATCH 5/8] server: Notify client about freed object so that it may free associated kernel object.
Jacek Caban
jacek at codeweavers.com
Fri Mar 15 13:19:16 CDT 2019
On 3/15/19 5:50 PM, Zebediah Figura wrote:
> On 03/15/2019 09:58 AM, Jacek Caban wrote:
>> Long term, we may consider making interface between server and device
>> manager more generic so that it could be used for messages other than IRPs.
>>
>> Signed-off-by: Jacek Caban <jacek at codeweavers.com>
>> ---
>> dlls/ntoskrnl.exe/ntoskrnl.c | 14 +++++++++++++-
>> server/device.c | 15 +++++++++++++++
>> server/protocol.def | 6 ++++++
>> 3 files changed, 34 insertions(+), 1 deletion(-)
>>
>>
>>
>>
>>
> Sorry if this is a dumb question, but why do we need this (and then, by
> extension, the whole infrastructure involving server changes)?
Generally speaking, it's meant to allow kernel objects implementation.
The main part in my consideration was ObReferenceObjectByHandle.
Although we could have more hacks around it without server support,
there are limitations to what's possible to hack. If we want to return
exactly the same object for given actual object (implemented usually in
server in Wine case), we need server involved in handle to object mapping.
Once we have that, there is another problem with object life time.
Driver may release its reference to the object, but an other process may
still have open handles. On Windows, those handles would keep object
reference count of the object, but on Wine that count is in server, not
ntoskrnl.exe. It means that only server knows when the object is
actually destroyed. If we don't want to leak in ntoskrnl.exe, we need
some mechanism to be notified about object being freed.
Also such kernel object reflecting a server object may be used as an
argument for other functions, like KeSetEvent. Unlike events initialized
with KeInitializeEvent, we don't have much control over such event. MRAC
does that: it creates an event, passes it by handle in ioctl(), driver
uses ObReferenceObjectByHandle and then KeSetEvent on this even. So we
need a way to implement such functions on top of kernel object pointers.
I tried storing handles on client side, but it had more problems as I
noted in [1]. Instead, we may just get a handle whenever we need them
and that's all we need to implement KeSetEvent on top of NtSetEvent.
In case of MRAC, it also needs FILE_OBJECT and PETHREAD. For
FILE_OBJECT, it checks some of its fields. I didn't debug details yet,
but found that some fake values satisfied its checks. PETHREAD follows
the pattern of bug 46205, where ObReferenceObjectByHandle needs to
return an object that we will be able to wait on later. On top of this
series, all we need is something similar to [2]. And once we have that,
KeGetCurrentThread (which you were interested in), would be a matter of
calling ObReferenceObjectByHandle with current thread handle (and
probably caching the result in TEB; also server would know thread client
pointer, so it could just pass it directly in get_next_device_request
when needed).
So there are multiple problems to solve. Some may be worked around
without server support, others not. I tried to make it generic enough to
fit all those requirements and allow using it for all objects. Note that
server already has limited mechanism for mapping device files and
devices to user pointers, which could also use the generic mechanism
instead.
Jacek
[1] https://source.winehq.org/patches/data/159405
[2] https://source.winehq.org/patches/data/161002
More information about the wine-devel
mailing list