Distinction between open file modes with fanotify - linux-kernel

I find it very very unclear what fanotify flags stand for.
Im using it for access control and would like to identify files opened for read and for write.
Taken from man:
FAN_OPEN_PERM An application wants to open a file or directory. The reader must write a response that determines whether the permission to open the filesystem object shall be granted.
Is it possible to allow only to read files, without write?
EDIT: I'm well aware of the fact that these can be realized when receiving FAN_CLOSE_WRITE and FAN_CLOSE_NOWRITE, but I want to make my access decision based on whether a file was opened for reading or for editing

Related

In Windows is it always necessary to use a handle to access a file?

In other words, is it possible to access a file without a handle being utilized?
You could use the CreateFile()-API to create a handle to the raw file-system and then parse the file structure by yourself (this is more work as it sounds!)
Though this would require admin-rights. This wouldn't trigger any hooks you have on CreateFile() or other file-related API-functions.
This wouldn't create a handle to the file but you still need a handle to the device.
For code running in user mode, any operation on a file will involve a handle of some kind, though not necessarily to the file in question. There are APIs that don't expose the handle to the programmer, but there is always one there.
In kernel mode, although it is usual to use handles for file operations, it is not necessary. For example, the file server component doesn't appear to open file handles when it is accessing a file on behalf of a remote user.

How to guarantee file integrity without mandatory file lock on OS X?

AFAIK, OS X is a BSD derivation, which doesn't have actual mandatory file locking. If so, it seems that I have no way to prevent writing access from other programs even while I am writing a file.
How to guarantee file integrity in such environment? I don't care integrity after my program exited, because that's now user's responsibility. But at least, I think I need some kind of guarantee while my program is running.
How do other programs guarantee file content integrity without mandatory locking? Especially database programs. If there's common technique or recommended practice, please let me know.
Update
I am looking for this for data layer of GUI application for non-engineer users. And currently, my program have this situations.
Data is too big that it cannot be fit to RAM. And even hard to be temporarily copied. So it cannot be read/written atomically, and should be used from disk directly while program is running.
A long running professional GUI content editor application used by humans who are non-engineers. Though users are not engineers, but they still can access the file simultaneously with Finder or another programs. So users can delete or write on currently using file accidentally. Problem is users don't understand what is actually happening, and expect program handles file integrity at least program is running.
I think the only way to guarantee file's integrity in current situation is,
Open file with system-wide exclusive mandatory lock. Now the file is program's responsibility.
Check for integrity.
Use the file as like external memory while program is running.
Write all the modifications.
Unlock. Now the file is user's responsibility.
Because OS X lacks system-wide mandatory lock, so now I don't know what to do for this. But still I believe there's a way to archive this kind of file integrity, which just I don't know. And I want to know how everybody else handles this.
This question is not about my programming error. That's another problem. Current problem is protecting data from another programs which doesn't respect advisory file lockings. And also, users are usually root and the program is running with same user, so trivial Unix file privilege is not useful.
You have to look at the problem that you are trying to actually solve with mandatory locking.
File content integrity is not guaranteed by mandatory locking; unless you keep your file locked 24/7; file integrity will still depend on all processes observing file format/access conventions (and can still fail due to hard drive errors etc.).
What mandatory locking protects you against is programming errors that (by accident, not out of malice) fail to respect the proper locking protocols. At the same time, that protection is only partial, since failure to acquire a lock (mandatory or not) can still lead to file corruption. Mandatory locking can also reduce possible concurrency more than needed. In short, mandatory locking provides more protection than advisory locking against software defects, but the protection is not complete.
One solution to the problem of accidental corruption is to use a library that is aggressively tested for preserving data integrity. One such library (there are others) is SQlite (see also here and here for more information). On OS X, Core Data provides an abstraction layer over SQLite as a data storage. Obviously, such an approach should be complemented by replication/backup so that you have protection against other causes for data corruption where the storage layer cannot help you (media failure, accidental deletion).
Additional protection can be gained by restricting file access to a database and allowing access only through a gateway (such as a socket or messaging library). Then you will just have a single process running that merely acquires a lock (and never releases it). This setup is fairly easy to test; the lock is merely to prevent having more than one instance of the gateway process running.
One simple solution would be to simply hide the file from the user until your program is done using it.
There are various ways to hide files. It depends on whether you're modifying an existing file that was previously visible to the user or creating a new file. Even if modifying an existing file, it might be best to create a hidden working copy and then atomically exchange its contents with the file that's visible to the user.
One approach to hiding a file is to create it in a location which is not normally visible to users. (That is, it's not necessary that the file be totally impossible for the user to reach, just out of the way so that they won't stumble on it.) You can obtain such a location using -[NSFileManager URLForDirectory:inDomain:appropriateForURL:create:error:] and passing NSItemReplacementDirectory and NSUserDomainMask for the first two parameters. See -replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error: method for how to atomically move the file into its file place.
You can set a file to be hidden using various APIs. You can use -[NSURL setResourceValue:forKey:error:] with the key NSURLIsHiddenKey. You can use the chflags() system call to set UF_HIDDEN. The old Unix standby is to use a filename starting with a period ('.').
Here's some details about this topic:
https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileCoordinators/FileCoordinators.html
Now I think the basic policy on OSX is something like this.
Always allow access by any process.
Always be prepared for shared data file mutation.
Be notified when other processes mutates the file content, and provide proper response on them. For example you can display an error to end users if other process is trying to access the file. And then users will learn that's bad, and will not do it again.

Does opening a file with Share-Delete allow others to write?

The FileShare enumeration offers various flags such as Read, Write, Delete, ... . Normally I'd think that sharing a file for deletion only allows deletion but nothing else (like reading).
However, I remotely recall that Windows only differentiates between read-only and full access to files, so actually sharing for deletion allows writing to the file as well. Sadly this is from many years back and I neither found the original source nor any related info. Is there a reliable spec on the actual behavior? Is it dependent on the OS or the FS?
Take a look at the documentation for the CreateFile Function.
FILE_SHARE_DELETE:
Enables subsequent open operations on a file or
device to request delete access. Otherwise, other processes cannot
open the file or device if they request delete access. If this flag is
not specified, but the file or device has been opened for delete
access, the function fails. Note Delete access allows both delete and
rename operations.
The documentation doesn't mention that read access is allowed, too.

How to read data using ReadFile when file has disabled sharing on read

I have a problem, i have a file who opened other process and this process defined in CreateFile non file sharing, then i have other application and i want read data from this
file in same time, but how to do.
I can't change file sharing in first application.
I can reach computer administrator right's, i can do changes in system, but probably "code" solution will be better for this problem if this can be done by code.
Can anyone help me?
How about using EasyHook and hook in the API to the CreateFile routine, in effect, your code will intercept the API and possibly change the dwShareMode parameter to make it FILE_SHARE_READ bitwise or FILE_SHARE_WRITE i.e. (FILE_SHARE_READ|FILE_SHARE_WRITE) and call the original hook to allow the CreateFile to work normally...
Use the backup API if you have sufficient privilege. Otherwise, note that these flags exist for a reason. If someone disabled sharing, it's disabled.
You want to call BackupRead, and MSDN notes the following:
a backup
application must have access to the
system-level access control settings,
the ACCESS_SYSTEM_SECURITY flag must
be specified in the dwDesiredAccess
parameter value passed to CreateFile.value passed to CreateFile.
parameter value passed to CreateFile.
One of the options is to use our RawDisk product, which lets you bypass system security restrictions and open files, which have been opened exclusively or the ones for which you don't have access rights. Note, that installing RawDisk itself requires admin rights, so RawDisk can't be used for intrusion to other's computer.
Another option is to use backup API, i.e. above mentioned BackupRead() Windows API function. Doing google search for BackupAPI will give you not just description of this function, but also several comments from users about what's involved in using this backup API

Lock file but allow usage by current process?

I want to be able to lock a file in Win32 so that it can only be used by my current process. The most obvious way to accomplish that seemed to be via CreateFile:
HANDLE file = ::CreateFile("c:\\foo.txt",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
However once that call has succeeded, the file is also apparently locked by my own process, ie. I get a "sharing violation" once the MFC framework stuff tries to open it.
Is there a convenient way to prevent access to the file by other processes but still allow it by mine? I'd rather not have to replace all the loading/saving framework code... Am I doing something wrong in the parameters I'm passing in to CreateFile?
From Creating and Opening Files:
An application also uses CreateFile to
specify whether it wants to share the
file for reading, writing, both, or
neither. This is known as the sharing
mode. An open file that is not shared
(dwShareMode set to zero) cannot be
opened again, either by the
application that opened it or by
another application, until its handle
has been closed. This is also referred
to as exclusive access.
See also How do the FILE_SHARE_* bits interact with the desired access bits?
I'm not aware of any simple way to do this. As far as more complex methods go, you could:
set up a special user name for accessing the file.
Open the file non-shared.
Edit the ACL to allow use only from the special user name
Close the file.
Impersonate that user
Open the file, allowing sharing
Close the file
Set the ACL back to allow other users access
Note that I'm not saying I'd recommend that at all -- it's ugly and more or less an abuse of the system -- but if you're sure you need to do this, it's one way that probably would work.

Resources