Can I get an event callback to my kernel driver when the boot process has completed, or when a user logs in?
The simple answer is no.
The long answer is yes, but why?
I'll answer the second part, because it's easier. You can easily register to recieve a notification when any process is launched. A short examination of Windows Internals will tell you that from Vista and up, the process userinit.exe is the first process to be executed in any given user session.
To the first part, this very much changes depending on your definition of boot process. Is it when a GUI is loaded? Is it when the computer can receive network requests? Does it matter which network requests (TCP/IP, SMB, RPC)?
The answer to each of these is very different.
When win32K has finished loading
When the TCP/IP stack drivers finish loading
When specific services (RPC, Server service) are done loading
What is the problem you're trying to solve?
Related
In KEXT, I am listening for file close via vnode or file scope listener. For certain (very few) files, I need to send file path to my system daemon which does some processing (this has to happen in daemon) and returns the result back to KEXT. The file close call needs to be blocked until I get response from daemon. Based on result I need to some operation in close call and return close call successfully. There is lot of discussion on KEXT communication related topic on the forum. But they are not conclusive and appears be very old (year 2002 around). This requirement can be handled by FtlSendMessage(...) Win32 API. I am looking for equivalent of that on Mac
Here is what I have looked at and want to summarize my understanding:
Mach message: Provides very good way of bidirectional communication using sender and reply ports with queueing mechansim. However, the mach message APIs (e.g. mach_msg, mach_port_allocate, bootstrap_look_up) don't appear to be KPIs. The mach API mach_msg_send_from_kernel can be used, but that alone will not help in bidirectional communication. Is my understanding right?
IOUserClient: This appears be more to do with communicating from User space to KEXT and then having some callbacks from KEXT. I did not find a way to initiate communication from KEXT to daemon and then wait for result from daemon. Am I missing something?
Sockets: This could be last option since I would have to implement entire bidirectional communication channel from KEXT to Daemon.
ioctl/sysctl: I don't know much about them. From what I have read, its not recommended option especially for bidirectional communication
RPC-Mig: Again I don't know much about them. Looks complicated from what I have seen. Not sure if this is recommended way.
KUNCUserNotification: This appears to be just providing notification to the user from KEXT. It does not meet my requirement.
Supported platform is (10.5 onwards). So looking at the requirement, can someone suggest and provide some pointers on this topic?
Thanks in advance.
The pattern I've used for that process is to have the user-space process initiate a socket connection to the KEXT; the KEXT creates a new thread to handle messages over that socket and sleeps the thread. When the KEXT detects an event it needs to respond to, it wakes the messaging thread and uses the existing socket to send data to the daemon. On receiving a response, control is passed back to the requesting thread to decide whether to veto the operation.
I don't know of any single resource that will describe that whole pattern completely, but the relevant KPIs are discussed in Mac OS X Internals (which seems old, but the KPIs haven't changed much since it was written) and OS X and iOS Kernel Programming (which I was a tech reviewer on).
For what it's worth, autofs uses what I assume you mean by "RPC-Mig", so it's not too complicated (MIG is used to describe the RPC calls, and the stub code it generates handles calling the appropriate Mach-message sending and receiving code; there are special options to generate kernel-mode stubs).
However, it doesn't need to do any lookups, as automountd (the user-mode daemon to which the autofs kext sends messages) has a "host special port" assigned to it. Doing the lookups to find an arbitrary service would be harder.
If you want to use the socket established with ctl_register() on the KExt side, then beware: The communication from kext to user space (via ctl_enqueuedata()) works OK. However opposite direction is buggy on 10.5.x and 10.6.x.
After about 70.000 or 80.000 send() calls with SOCK_DGRAM in the PF_SYSTEM domain complete net stack breaks with disastrous consequences for complete system (hard turning off is the only way out). This has been fixed in 10.7.0. I workaround by using setsockopt() in our project for the direction from user space to kext as we only send very small data (just to allow/disallow some operation).
I am building a Windows service that will watch for specific occurrences of events and disk activity. When such an event occurs my plan is to alert the user to the event via a client app, and provide remediation if necessary. I have (mostly) completed both the client and service components, which work great... unless the client app isn't running.
In short, I am looking for a way to start up the client app from the Windows service via CreateProcess to provide information to the user. However, it appears the service can't even see the file/folder of the client app to execute it. I suspect this is due to the credentials under which the service is running, or maybe due to service level restrictions, but wanted to reach out for some advise before I get into this any deeper.
So, the obvious question first... am I thinking about this clearly? Is the architecture plan sound, or should I look at another method? I would prefer not to re-do any of the work I have already completed, but obviously want to make sure the plan and process is solid.
Question #2, what are the limitations I face with this model? Is there a service account that will allow this level of access?
I am obviously struggling with this right now, so any thoughts or assistance will be greatly appreciated!
Thanks,
Kris
As others have mentioned already, you can't (easily) launch an application directly from the service, so I think the easiest way around the problem is to create a process that starts on login and runs with the credentials of the logged in user, eg an app that sits in the system tray, and it opens up a named pipe or a network port to the service. If the service needs to alert the user, it sends a message down that channel and then the client process can either show its own UI or launch an application. Interprocess communication using pipes or ports are the simplest way to deal with the restrictions on session 0 processes.
A Windows service does not have access to the user session in Vista and above, so it is blocked from starting an executable on that session. You can download a white paper from Microsoft that goes into detail: Impact of Session 0 Isolation on Services and Drivers in Windows.
Since Vista, services run in session 0 and the user's desktop is always in a different session. Thus you need to work hard to start a service on the user's desktop.
It can be done but it is pretty tricky. Details can be found here: http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx?wa=wsignin1.0
I need to track to a log when a service or application in Windows is started, stopped, and whether it exits successfully or with an error code.
I understand that many services do not log their own start and stop times, or if they exit correctly, so it seems the way to go would have to be inserting a hook into the API that will catch when services/applications request a process space and relinquish it.
My question is what function do I need to hook in order to accomplish this, and is it even possible? I need it to work on Windows XP and 7, both 64-bit.
I think your best bet is to use a device driver. See PsSetCreateProcessNotifyRoutine.
Windows Vista has NotifyServiceStatusChange(), but only for single services. On earlier versions, it's not possible other than polling for changes or watching the event log.
If you're looking for a user-space solution, EnumProcesses() will return a current list. But it won't signal you with changes, you'd have to continually poll it and act on the differences.
If you're watching for a specific application or set of applications, consider assigning them to Job Objects, which are all about allowing you to place limits on processes and manage them externally. I think you could even associate Explorer with a job object, then all tasks launched by the user would be associated with your job object automatically. Something to look into, perhaps.
I'd like to call my app from my driver when an interesting event happens in the Windows kernel. I need to be able to pass at least 4 bytes of data back to user mode. How to achieve this? These events might happen quite, but not too, often, so I don't want to build a queue system and use IOCTLs.
I was thinking of something like the driver gets loaded, the user mode app registers its callback using IOCTL and kernel keeps calling that callback when events happen and finally the user mode client unregisters the callback and no more data is send to user mode. Is this possible?
I'm new to kernel programming, so after a day of googling I decided to ask here. I've noticed that there isn't much discussion about the kernel and drivers. And even less proper docs.
I'm very interested in the answer to another question regarding watchdog timers for Windows services (see here). That answer stated:
I have also used an internal watchdog system running in another thread. That thread looks at the main thread for activity like log output or a toggling event. If the activity is not seen then the service is considered hung and I shutdown the service.
In this case you can configure windows to auto-restart a stopped service and that might clear the problem (as long as it's not an internal logic bug).
Also services I work with have text logs that are written to a log. In addition for services that are about to "sleep for a bit", I log the time for the next wake up. I use MTAIL to watch a log for output."
Could anyone give some sample code how to use an internal watchdog running in another thread, since I currently have a task to develop a windows service which will be able to self restart in case it failed, hung up, etc.
I really appreciate your help.
I'm not a big fan of running a watchdog as a thread in the process you're watching. That means if the whole process hangs for some reason, the watchdog won't work.
Watchdogs are an idea lifted from the hardware world and they had it right. Use an external circuit as simple as possible (so it can be provably correct). Typical watchdogs simply ran an timer and, if the process hadn't done something before the timer expired (like access a memory location the watchdog was watching), the whole thing was reset. When the watchdog was "kicked", it would restart the timer.
The act of the process kicking the watchdog protected that process from summary termination.
My advice would be to write a very simple stand-alone program which just monitored an event (such as file update time being modified). If that event didn't occur within the required time, kill the process being watched (and let Windows restart it).
Then have your watched program periodically rewrite that file.
Other approaches you might want to consider besides regularly modifying the lastwritetime of a file would be to create a proper performance counter or even a WMI object. We do the later in our build infrastructure, the 'trick' is to find a meaningful work unit in the service being monitored and pulse your 'heartbeat' each time a unit is finished.
The advantage of WMI or Perf Counters over a the file approach is that you then become visible to a whole bunch of professional MIS / management tools. This can add a lot of value.
You can configure from service properties to self restart in case of failure
Services -> right-click your service -> Properties -> First failure : restart the service -> Second failure : restart the service -> Subsequent failure : restart