Hi,
I'm one of the Google Summer of Code students and I'm working on the ClamAV integration in wine. Today I was discussing an issue with my mentor and he suggested to post it here.
Currently I'm working on a scan-after-write functionality: Whenever a file was changed the virusscanner checks the file.
My plan is to hook in NtWriteFile() (dlls/ntdll/file.c), because whenever a windows program writes to a file this function is called. Within this function the file is accessed using its unix_handle.
The problem is that I need to know the unix filename for clamAV to access the file, but I see no proper way or function to get it as long as I just know the unix_handle or fd.
Possible solutions so far:
1. searching /proc/self/fd/%d for the name. This would be an easy but very ugly solution.
2. maintaining a table mapping unix_handles to filenames from within NtCreateFile(). Hence I don't have the feeling that this is a good solution.
3. storing the unix filename in the wineserver handle object when it's created. This is probably the right place to keep this information but it would require some changes to the wineserver. If I understand it right it is already planned to implement something like this ("lookup_name" in server/object.c)
But maybe I just missed an even better approach. What would you recommend to do? Any comment is appreciated.
Cheers, Chris
Christoph Probst chris-usenet@netzpunkt.org writes:
My plan is to hook in NtWriteFile() (dlls/ntdll/file.c), because whenever a windows program writes to a file this function is called. Within this function the file is accessed using its unix_handle.
The problem is that I need to know the unix filename for clamAV to access the file, but I see no proper way or function to get it as long as I just know the unix_handle or fd.
You can't do that in general. In Unix a file can have multiple names, or even none at all, there's simply no way to get a filename from a handle. On Linux you can use /proc/self/fd but that's not very portable.
Hi.
Alexandre Julliard wrote:
You can't do that in general. In Unix a file can have multiple names, or even none at all, there's simply no way to get a filename from a handle. On Linux you can use /proc/self/fd but that's not very portable.
So what do you think about the solution that the wineserver stores the filename in the file object when the object is created?
Just like wine_server_handle_to_fd() there would be a wine_server_handle_to_filename() that returns the filename.
Any objections to this?
Chris
Christoph Probst chris-usenet@netzpunkt.org writes:
So what do you think about the solution that the wineserver stores the filename in the file object when the object is created?
Just like wine_server_handle_to_fd() there would be a wine_server_handle_to_filename() that returns the filename.
Any objections to this?
Yes. Like I said, there's no guarantee that the file even has a name, or that it is accessible under the name that was used to open it, so we can't provide such an API.
Christoph Probst wrote:
Hi.
Alexandre Julliard wrote:
You can't do that in general. In Unix a file can have multiple names, or even none at all, there's simply no way to get a filename from a handle. On Linux you can use /proc/self/fd but that's not very portable.
So what do you think about the solution that the wineserver stores the filename in the file object when the object is created?
Just like wine_server_handle_to_fd() there would be a wine_server_handle_to_filename() that returns the filename.
Any objections to this?
just for sake of completeness: how about enhancing ClamAV so that it takes a fd (instead of a filename) as its input ? A+
Eric Pouech eric.pouech@wanadoo.fr writes:
Christoph Probst wrote:
Hi.
Alexandre Julliard wrote:
You can't do that in general. In Unix a file can have multiple names, or even none at all, there's simply no way to get a filename from a handle. On Linux you can use /proc/self/fd but that's not very portable.
So what do you think about the solution that the wineserver stores the filename in the file object when the object is created?
Just like wine_server_handle_to_fd() there would be a wine_server_handle_to_filename() that returns the filename.
Any objections to this?
just for sake of completeness: how about enhancing ClamAV so that it takes a fd (instead of a filename) as its input ? A+
It does http://www.clamav.net/doc/0.88.2/html/node24.html
| The daemon is fully configurable via the clamd.conf file 5. clamd recognizes the following commands: <...> | STREAM Scan stream: clamd will return a new port number you should connect to and send data to scan.
You not need to use following command:
| SCAN file/directory Scan file or directory (recursively) with archive support enabled (a full path is required).
Hi.
Eric Pouech wrote:
just for sake of completeness: how about enhancing ClamAV so that it takes a fd (instead of a filename) as its input ?
It looks like as if fd are already supported somehow. Need to have a closer look at that ...
But I found an even better alternative: ClamAV supports a STREAM command which allows a client to send a string to the scanner. This allows to scan a string even before it is written to disk.
Thanks for your answer!
Chris
just for sake of completeness: how about enhancing ClamAV so that it takes a fd (instead of a filename) as its input ?
It looks like as if fd are already supported somehow. Need to have a closer look at that ...
But I found an even better alternative: ClamAV supports a STREAM command which allows a client to send a string to the scanner. This allows to scan a string even before it is written to disk.
I think that this will totally kill performance. Many programs can create temporary files that later get deleted. There's no point in monitoring writes to those.
The only way to tell is to wait until the handle gets closed by wine. Then I imagine you'd use fstat on a copy of the handle and see if there are any hard links (i.e. directory entries) pointing to that inode, and if there are (i.e. if the file is still acessible), only then you'd scan it. You'd also need to keep track of any handle copies that wine holds, if there are any -- I don't know offhand if wine itself duplicates "user" file handles, nor whether there's a windows API to do so.
Similarly, programs such as databases may reorganize huge swaths of file(s), writing a lot of stuff that has no relevance to a virus scanner.
I think that no-brainer approaches will result in exactly the same performance-robbing solution as McAffe and Symantec products evolved to.
I think there needs to be some more serious thinking done before implementing your project.
Cheers, Kuba
On Saturday 24 June 2006 07:06, Christoph Probst wrote:
Hi.
Alexandre Julliard wrote:
You can't do that in general. In Unix a file can have multiple names, or even none at all, there's simply no way to get a filename from a handle. On Linux you can use /proc/self/fd but that's not very portable.
So what do you think about the solution that the wineserver stores the filename in the file object when the object is created?
Just like wine_server_handle_to_fd() there would be a wine_server_handle_to_filename() that returns the filename.
A way to possibly do what you want to do is to duplicate the file handle, and to hack on ClamAV to scan a file given a handle to it.
On unices you can open a file, hold a handle to it, and then remove the directory entry (rm file) -- the file will exist on the disk without a directory entry, for as long as the file handle is open. I don't think you could do that under e.g. Windows, so Unix is different here.
In general the only way to get at a file knowing its handle is to use a duplicate handle. That'd be the only robust way AFAIK.
Cheers, Kuba