Use minifilter driver to help enforce shared file access control

Hi everyone,

(This is a bit long, please bear with me)

I am using a minifilter driver to help me implement a Windows
file access control system that has the following components:

  1. A Samba server running on a Linux server.
  2. Windows (Vista and above) clients accessing the Samba shares.

The basic design works as follows(ignoring minifilter driver config ops):

  1. Windows user tries to open a file on a share.
  2. In its PreCreate handler, a minifilter driver gets the file name and
    determines if the file is on the target share. If so, it logs the file
    open request (PID/process name) to an user application, passing through
    file requests that target other volumes. The PreCreate handler waits for
    an application ack before returning.
  3. The user application puts the shared file open request on a queue, say,
    file_log_list, before calling FilterReplyMessage() to ack the driver.
  4. The Samba server receives the file open request and issues its own open
    request to the Linux FS. I have a Linux FS monitor application watching
    the shares, receiving notifications on the Samba server’s file requests.
  5. My Linux FS monitor application sends the file request (share/file name)
    to the Windows client originating the file open request.
  6. The Windows application scans the file log queue for the target file
    and returns the originating Windows process executable and its digital
    signature info to the Linux FS monitor application.
  7. The Linux FS monitor application uses a Windows application white list
    to determine if the open request should be allowed and the decision is
    injected into the Linux FS which eventually returns the open request
    result back to the Windows client.
  8. In its PostCreate handler, the minifilter driver pretty much just
    print out the IoStatus.Status value for debugging purpose.

This design works for some applications. For example, only MS Office
can open the Office files if that is what the white list policy wants.

Here is the problem that I don’t know how to approach and I am hoping for
advice from folks here:

If I run Visual Studio to build a project in the shared folder,
the executable file can be created but attempt to run from the VS would
fail. A “hello world” console app would open a window without printing
any message. I have added all VS exe’s to the white list. In fact, the
following tests all work:

  1. If I copy the generated EXE to the desktop and run from there.
  2. If I just white-list everything and do not load the minifilter driver.
  3. If I attach the minispy driver to the network share, replacing my own driver.

I’d really appreciate it if any of you can give me some hints, or completely
different methods to solve this kind of network file access control
problem. The requirement is to allow the server to use client program
white list to authenticate client file access.

Unfortunately, Windows doesn’t have an equivalent to the Linux fanotify API,
which is why I had to use a minifilter driver to get notifications of file access events.

Thank you very much!

Youlin

Have you run ProcMon on the client to see the I/O before the hang? Also, have you checked the threads of the hanging process from the kernel debugger?

Thank you, Scott, for responding!

I was thinking about using ProcMon to take a look at the hanging sequence and will do so next.

No, I haven’t thought about using the kernel debugger as you suggested. Will definitely pursue this.

Thanks again!

An update of this problem:

The problem where the executable built from VS on the network share hangs is caused by a deadlock.

Here is the sequence of events leading to the deadlock:

  1. The VS-built executable on the share starts to run, opening itself or a DLL which is also on the share.
  2. The driver’s pre_create callback is called and it calls FltSendMessage to send a log (executable PID and the target file) to the user level monitoring process which is responsible for receiving messages from the driver-user queue.
  3. The user level monitoring process tries to get the executable’s full path from its PID, by calling OpenProcess(PID) and QueryFullProcessImageName().
  4. The OpenProcess(PID) triggers another IRP_MJ_CREATE, causing the pre_create callback to be called again. At this point the user level monitoring process blocks in OpenProcess().
  5. Because the target executable file is on the monitored share, pre_create callback calls FltSendMessage() again to log its open.
  6. Because the user level monitoring process is being blocked inside OpenProcess(), it can’t drain the driver-user message queue, leading to a deadlock.

The solution is to return FLT_PREOP_SUCCESS_NO_CALLBACK in step 5 above, without calling FltSendMessage because we don’t need to worry about our own monitoring process for issuing illegal file access and hence there is no need to log its access to the file on the share.

Thanks Scott again for the help!

Youlin

1 Like