Re: Synchronous communication for Antivirus application.
Re: Synchronous communication for Antivirus application.
- Subject: Re: Synchronous communication for Antivirus application.
- From: Terry Lambert <email@hidden>
- Date: Wed, 18 Aug 2010 11:45:34 -0700
On Aug 17, 2010, at 10:48 PM, Deena Awate wrote:
> I am working on an antivirus project for MAC. We have taken vnode level file system activity monitor code from MAC OS X internals book as our guide. What we are trying to achieve is monitoring on the vnode scope. When a file operation takes place at the vnode level the kernel will pass on the filename to usermode application for scanning. Meanwhile the kernel needs to wait for the scanning to complete and look at the return value. The user mode app will wake up the kernel once scanning is done and pass the scan result down to the kernel. Based on the scan result the kernel then either allows or denies the request. So basically we want to achieve synchronous communication between the kernel extension and the user mode application. We are newbies on MAC. We read documentation but is confusing as to how we can create event in user mode and pass it down to kernel on which the kernel will wait. If you could point us to a sample piece of code or clear documentation on how we can achieve our objective it will be great. Which are the synchronisation objects to be used in user mode and which ones to use in user mode. Is this the right design ? I have gone through posts on the forum but did not get how to achieve our objective.
> Thanks,
> Deena
In general: Do Not Make The Kernel Wait (tm).
My first suggestion is that you should push the smallest amount of information necessary to answer the kernels question(s) down from user space to kernel space through one of the allowed mechanisms (and store the information in the kernel, in pageable memory). And then not depend on user space, unless it wants to push you more data, e.g. a virus pattern file update happens.
If you can't do it in a small amount of space, then your next option is to load it into pageable memory in the user space process so that the user space process can answer any kernel queries *immediately*, so as not to make the kernel wait. If you do this, you should make your own process immune from triggering up-calls from the kernel to user space in order to avoid deadly embrace deadlocks (e.g. as a result of paging). You should also consider making 'root' owned processes immune as well.
You should minimize the interfaces your user space process uses, in order to avoid using a framework which under the covers talks to another process which triggers an up-call. The general recommendation in this case is to limit yourself to POSIX file I/O, and do no networking (networking requires name resolution which talks to mDNSResponder which runs as non-root which can trigger up-calls). You never know what a framework is going to do to try and service your request -- it could be a huge amount of work involving a dozen different processes.
If you do up-calls at all, you need to provide a mechanism to time out the kernel's requests. This mechanism should be implemented in the kernel, and if the user space process doesn't respond in a reasonable period of time (in general: 30 seconds or less is reasonable, since that's 10 seconds of delay and 20 seconds of you causing an application to SPOD), you should revoke its authority to answer your questions. SPOD any longer than that, and the human hooked up to the keyboard is going to start force-quitting things. The user space process should get an error when it tries next time, which it should interpret as you (in the kernel) telling it to kill itself and come back when it can answer your questions in a reasonable period of time.
Obviously, this is not a synchronous interface -- and it's not intended to be. If the kernel becomes unresponsive, your entire system locks up, so you have to avoid that happening because of a KEXT you write.
If you want to see an example of a time-out up-call interface that you should probably *NOT* copy faithfully, see the functions identitysvc() and kauth_resolver_submit() in the xnu source file bsd/kern/kern_credential.c (you shouldn't try to copy it because you shouldn't make the kernel wait, and because you need to audit all the code paths and be sure you don't rely on other processes, and because you can't implement a system call like identitysvc()). But it will give you the overall picture.
The general methods to use for user/kernel communication are (in my personal highest-to-lowest preference order):
o Don't need to do it in the first place
o IOUserClient
o Control socket
o BSD device file
o sysctl
Documentation on these and others is available from <http://developer.apple.com/>, along with source code examples.
-- Terry _______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden