diff options
Diffstat (limited to 'man7/fanotify.7')
-rw-r--r-- | man7/fanotify.7 | 1456 |
1 files changed, 0 insertions, 1456 deletions
diff --git a/man7/fanotify.7 b/man7/fanotify.7 deleted file mode 100644 index b0b5121..0000000 --- a/man7/fanotify.7 +++ /dev/null @@ -1,1456 +0,0 @@ -.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de> -.\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com> -.\" -.\" SPDX-License-Identifier: Linux-man-pages-copyleft -.TH fanotify 7 2023-10-31 "Linux man-pages 6.7" -.SH NAME -fanotify \- monitoring filesystem events -.SH DESCRIPTION -The fanotify API provides notification and interception of -filesystem events. -Use cases include virus scanning and hierarchical storage management. -In the original fanotify API, only a limited set of events was supported. -In particular, there was no support for create, delete, and move events. -The support for those events was added in Linux 5.1. -(See -.BR inotify (7) -for details of an API that did notify those events pre Linux 5.1.) -.P -Additional capabilities compared to the -.BR inotify (7) -API include the ability to monitor all of the objects -in a mounted filesystem, -the ability to make access permission decisions, and the -possibility to read or modify files before access by other applications. -.P -The following system calls are used with this API: -.BR fanotify_init (2), -.BR fanotify_mark (2), -.BR read (2), -.BR write (2), -and -.BR close (2). -.SS fanotify_init(), fanotify_mark(), and notification groups -The -.BR fanotify_init (2) -system call creates and initializes an fanotify notification group -and returns a file descriptor referring to it. -.P -An fanotify notification group is a kernel-internal object that holds -a list of files, directories, filesystems, and mounts for which -events shall be created. -.P -For each entry in an fanotify notification group, two bit masks exist: the -.I mark -mask and the -.I ignore -mask. -The mark mask defines file activities for which an event shall be created. -The ignore mask defines activities for which no event shall be generated. -Having these two types of masks permits a filesystem, mount, or -directory to be marked for receiving events, while at the same time -ignoring events for specific objects under a mount or directory. -.P -The -.BR fanotify_mark (2) -system call adds a file, directory, filesystem, or mount to a -notification group and specifies which events -shall be reported (or ignored), or removes or modifies such an entry. -.P -A possible usage of the ignore mask is for a file cache. -Events of interest for a file cache are modification of a file and closing -of the same. -Hence, the cached directory or mount is to be marked to receive these -events. -After receiving the first event informing that a file has been modified, -the corresponding cache entry will be invalidated. -No further modification events for this file are of interest until the file -is closed. -Hence, the modify event can be added to the ignore mask. -Upon receiving the close event, the modify event can be removed from the -ignore mask and the file cache entry can be updated. -.P -The entries in the fanotify notification groups refer to files and -directories via their inode number and to mounts via their mount ID. -If files or directories are renamed or moved within the same mount, -the respective entries survive. -If files or directories are deleted or moved to another mount or if -filesystems or mounts are unmounted, the corresponding entries are deleted. -.SS The event queue -As events occur on the filesystem objects monitored by a notification group, -the fanotify system generates events that are collected in a queue. -These events can then be read (using -.BR read (2) -or similar) -from the fanotify file descriptor -returned by -.BR fanotify_init (2). -.P -Two types of events are generated: -.I notification -events and -.I permission -events. -Notification events are merely informative and require no action to be taken -by the receiving application with one exception: if a valid file descriptor -is provided within a generic event, the file descriptor must be closed. -Permission events are requests to the receiving application to decide -whether permission for a file access shall be granted. -For these events, the recipient must write a response which decides whether -access is granted or not. -.P -An event is removed from the event queue of the fanotify group -when it has been read. -Permission events that have been read are kept in an internal list of the -fanotify group until either a permission decision has been taken by -writing to the fanotify file descriptor or the fanotify file descriptor -is closed. -.SS Reading fanotify events -Calling -.BR read (2) -for the file descriptor returned by -.BR fanotify_init (2) -blocks (if the flag -.B FAN_NONBLOCK -is not specified in the call to -.BR fanotify_init (2)) -until either a file event occurs or the call is interrupted by a signal -(see -.BR signal (7)). -.P -After a successful -.BR read (2), -the read buffer contains one or more of the following structures: -.P -.in +4n -.EX -struct fanotify_event_metadata { - __u32 event_len; - __u8 vers; - __u8 reserved; - __u16 metadata_len; - __aligned_u64 mask; - __s32 fd; - __s32 pid; -}; -.EE -.in -.P -Information records are -supplemental pieces of information that -may be provided alongside the generic -.I fanotify_event_metadata -structure. -The -.I flags -passed to -.BR fanotify_init (2) -have influence over the type of information records that -may be returned for an event. -For example, -if a notification group is initialized with -.B FAN_REPORT_FID -or -.BR FAN_REPORT_DIR_FID , -then event listeners should also expect to receive a -.I fanotify_event_info_fid -structure alongside the -.I fanotify_event_metadata -structure, -whereby file handles are used to -identify filesystem objects -rather than file descriptors. -Information records may also be stacked, -meaning that using the various -.B FAN_REPORT_* -flags in conjunction with one another is supported. -In such cases, -multiple information records can be returned for an event -alongside the generic -.I fanotify_event_metadata -structure. -For example, -if a notification group is initialized with -.B FAN_REPORT_TARGET_FID -and -.BR FAN_REPORT_PIDFD , -then an event listener should expect to receive up to two -.I fanotify_event_info_fid -information records and one -.I fanotify_event_info_pidfd -information record alongside the generic -.I fanotify_event_metadata -structure. -Importantly, -fanotify provides no guarantee around -the ordering of information records -when a notification group is initialized with a -stacked based configuration. -Each information record has a nested structure of type -.IR fanotify_event_info_header . -It is imperative for event listeners to inspect the -.I info_type -field of this structure in order to -determine the type of information record that -had been received for a given event. -.P -In cases where an fanotify group -identifies filesystem objects by file handles, -event listeners should also expect to -receive one or more of the below -information record objects alongside the generic -.I fanotify_event_metadata -structure within the read buffer: -.P -.in +4n -.EX -struct fanotify_event_info_fid { - struct fanotify_event_info_header hdr; - __kernel_fsid_t fsid; - unsigned char handle[]; -}; -.EE -.in -.P -In cases where an fanotify group is initialized with -.BR FAN_REPORT_PIDFD , -event listeners should expect to receive the below -information record object alongside the generic -.I fanotify_event_metadata -structure within the read buffer: -.P -.in +4n -.EX -struct fanotify_event_info_pidfd { - struct fanotify_event_info_header hdr; - __s32 pidfd; -}; -.EE -.in -.P -In case of a -.B FAN_FS_ERROR -event, -an additional information record describing the error that occurred -is returned alongside the generic -.I fanotify_event_metadata -structure within the read buffer. -This structure is defined as follows: -.P -.in +4n -.EX -struct fanotify_event_info_error { - struct fanotify_event_info_header hdr; - __s32 error; - __u32 error_count; -}; -.EE -.in -.P -All information records contain a nested structure of type -.IR fanotify_event_info_header . -This structure holds meta-information about the information record -that may have been returned alongside the generic -.I fanotify_event_metadata -structure. -This structure is defined as follows: -.P -.in +4n -.EX -struct fanotify_event_info_header { - __u8 info_type; - __u8 pad; - __u16 len; -}; -.EE -.in -.P -For performance reasons, it is recommended to use a large -buffer size (for example, 4096 bytes), -so that multiple events can be retrieved by a single -.BR read (2). -.P -The return value of -.BR read (2) -is the number of bytes placed in the buffer, -or \-1 in case of an error (but see BUGS). -.P -The fields of the -.I fanotify_event_metadata -structure are as follows: -.TP -.I event_len -This is the length of the data for the current event and the offset -to the next event in the buffer. -Unless the group identifies filesystem objects by file handles, the value of -.I event_len -is always -.BR FAN_EVENT_METADATA_LEN . -For a group that identifies filesystem objects by file handles, -.I event_len -also includes the variable length file identifier records. -.TP -.I vers -This field holds a version number for the structure. -It must be compared to -.B FANOTIFY_METADATA_VERSION -to verify that the structures returned at run time match -the structures defined at compile time. -In case of a mismatch, the application should abandon trying to use the -fanotify file descriptor. -.TP -.I reserved -This field is not used. -.TP -.I metadata_len -This is the length of the structure. -The field was introduced to facilitate the implementation of -optional headers per event type. -No such optional headers exist in the current implementation. -.TP -.I mask -This is a bit mask describing the event (see below). -.TP -.I fd -This is an open file descriptor for the object being accessed, or -.B FAN_NOFD -if a queue overflow occurred. -With an fanotify group that identifies filesystem objects by file handles, -applications should expect this value to be set to -.B FAN_NOFD -for each event that is received. -The file descriptor can be used to access the contents -of the monitored file or directory. -The reading application is responsible for closing this file descriptor. -.IP -When calling -.BR fanotify_init (2), -the caller may specify (via the -.I event_f_flags -argument) various file status flags that are to be set -on the open file description that corresponds to this file descriptor. -In addition, the (kernel-internal) -.B FMODE_NONOTIFY -file status flag is set on the open file description. -This flag suppresses fanotify event generation. -Hence, when the receiver of the fanotify event accesses the notified file or -directory using this file descriptor, no additional events will be created. -.TP -.I pid -If flag -.B FAN_REPORT_TID -was set in -.BR fanotify_init (2), -this is the TID of the thread that caused the event. -Otherwise, this the PID of the process that caused the event. -.P -A program listening to fanotify events can compare this PID -to the PID returned by -.BR getpid (2), -to determine whether the event is caused by the listener itself, -or is due to a file access by another process. -.P -The bit mask in -.I mask -indicates which events have occurred for a single filesystem object. -Multiple bits may be set in this mask, -if more than one event occurred for the monitored filesystem object. -In particular, -consecutive events for the same filesystem object and originating from the -same process may be merged into a single event, with the exception that two -permission events are never merged into one queue entry. -.P -The bits that may appear in -.I mask -are as follows: -.TP -.B FAN_ACCESS -A file or a directory (but see BUGS) was accessed (read). -.TP -.B FAN_OPEN -A file or a directory was opened. -.TP -.B FAN_OPEN_EXEC -A file was opened with the intent to be executed. -See NOTES in -.BR fanotify_mark (2) -for additional details. -.TP -.B FAN_ATTRIB -A file or directory metadata was changed. -.TP -.B FAN_CREATE -A child file or directory was created in a watched parent. -.TP -.B FAN_DELETE -A child file or directory was deleted in a watched parent. -.TP -.B FAN_DELETE_SELF -A watched file or directory was deleted. -.TP -.B FAN_FS_ERROR -A filesystem error was detected. -.TP -.B FAN_RENAME -A file or directory has been moved to or from a watched parent directory. -.TP -.B FAN_MOVED_FROM -A file or directory has been moved from a watched parent directory. -.TP -.B FAN_MOVED_TO -A file or directory has been moved to a watched parent directory. -.TP -.B FAN_MOVE_SELF -A watched file or directory was moved. -.TP -.B FAN_MODIFY -A file was modified. -.TP -.B FAN_CLOSE_WRITE -A file that was opened for writing -.RB ( O_WRONLY -or -.BR O_RDWR ) -was closed. -.TP -.B FAN_CLOSE_NOWRITE -A file or directory that was opened read-only -.RB ( O_RDONLY ) -was closed. -.TP -.B FAN_Q_OVERFLOW -The event queue exceeded the limit on number of events. -This limit can be overridden by specifying the -.B FAN_UNLIMITED_QUEUE -flag when calling -.BR fanotify_init (2). -.TP -.B FAN_ACCESS_PERM -An application wants to read a file or directory, for example using -.BR read (2) -or -.BR readdir (2). -The reader must write a response (as described below) -that determines whether the permission to -access the filesystem object shall be granted. -.TP -.B 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. -.TP -.B FAN_OPEN_EXEC_PERM -An application wants to open a file for execution. -The reader must write a response that determines whether the permission to -open the filesystem object for execution shall be granted. -See NOTES in -.BR fanotify_mark (2) -for additional details. -.P -To check for any close event, the following bit mask may be used: -.TP -.B FAN_CLOSE -A file was closed. -This is a synonym for: -.IP -.in +4n -.EX -FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE -.EE -.in -.P -To check for any move event, the following bit mask may be used: -.TP -.B FAN_MOVE -A file or directory was moved. -This is a synonym for: -.IP -.in +4n -.EX -FAN_MOVED_FROM | FAN_MOVED_TO -.EE -.in -.P -The following bits may appear in -.I mask -only in conjunction with other event type bits: -.TP -.B FAN_ONDIR -The events described in the -.I mask -have occurred on a directory object. -Reporting events on directories requires setting this flag in the mark mask. -See -.BR fanotify_mark (2) -for additional details. -The -.B FAN_ONDIR -flag is reported in an event mask only if the fanotify group identifies -filesystem objects by file handles. -.P -Information records that are supplied alongside the generic -.I fanotify_event_metadata -structure will always contain a nested structure of type -.IR fanotify_event_info_header . -The fields of the -.I fanotify_event_info_header -are as follows: -.TP -.I info_type -A unique integer value representing -the type of information record object received for an event. -The value of this field can be set to one of the following: -.BR FAN_EVENT_INFO_TYPE_FID , -.BR FAN_EVENT_INFO_TYPE_DFID , -.BR FAN_EVENT_INFO_TYPE_DFID_NAME , -or -.BR FAN_EVENT_INFO_TYPE_PIDFD . -The value set for this field -is dependent on the flags that have been supplied to -.BR fanotify_init (2). -Refer to the field details of each information record object type below -to understand the different cases in which the -.I info_type -values can be set. -.TP -.I pad -This field is currently not used by any information record object type -and therefore is set to zero. -.TP -.I len -The value of -.I len -is set to the size of the information record object, -including the -.IR fanotify_event_info_header . -The total size of all additional information records -is not expected to be larger than -.RI ( event_len -\- -.IR metadata_len ). -.P -The fields of the -.I fanotify_event_info_fid -structure are as follows: -.TP -.I hdr -This is a structure of type -.IR fanotify_event_info_header . -For example, when an fanotify file descriptor is created using -.BR FAN_REPORT_FID , -a single information record is expected to be attached to the event with -.I info_type -field value of -.BR FAN_EVENT_INFO_TYPE_FID . -When an fanotify file descriptor is created using the combination of -.B FAN_REPORT_FID -and -.BR FAN_REPORT_DIR_FID , -there may be two information records attached to the event: -one with -.I info_type -field value of -.BR FAN_EVENT_INFO_TYPE_DFID , -identifying a parent directory object, and one with -.I info_type -field value of -.BR FAN_EVENT_INFO_TYPE_FID , -identifying a child object. -Note that for the directory entry modification events -.BR FAN_CREATE , -.BR FAN_DELETE , -.BR FAN_MOVE , -and -.BR FAN_RENAME , -an information record identifying the created/deleted/moved child object -is reported only if an fanotify group was initialized with the flag -.BR FAN_REPORT_TARGET_FID . -.TP -.I fsid -This is a unique identifier of the filesystem containing the object -associated with the event. -It is a structure of type -.I __kernel_fsid_t -and contains the same value as -.I f_fsid -when calling -.BR statfs (2). -.TP -.I handle -This field contains a variable-length structure of type -.IR "struct file_handle" . -It is an opaque handle that corresponds to a specified object on a -filesystem as returned by -.BR name_to_handle_at (2). -It can be used to uniquely identify a file on a filesystem and can be -passed as an argument to -.BR open_by_handle_at (2). -If the value of -.I info_type -field is -.BR FAN_EVENT_INFO_TYPE_DFID_NAME , -the file handle is followed by a null terminated string that identifies the -created/deleted/moved directory entry name. -For other events such as -.BR FAN_OPEN , -.BR FAN_ATTRIB , -.BR FAN_DELETE_SELF , -and -.BR FAN_MOVE_SELF , -if the value of -.I info_type -field is -.BR FAN_EVENT_INFO_TYPE_FID , -the -.I handle -identifies the object correlated to the event. -If the value of -.I info_type -field is -.BR FAN_EVENT_INFO_TYPE_DFID , -the -.I handle -identifies the directory object correlated to the event or the parent directory -of a non-directory object correlated to the event. -If the value of -.I info_type -field is -.BR FAN_EVENT_INFO_TYPE_DFID_NAME , -the -.I handle -identifies the same directory object that would be reported with -.B FAN_EVENT_INFO_TYPE_DFID -and the file handle is followed by a null terminated string that identifies the -name of a directory entry in that directory, or '.' to identify the directory -object itself. -.P -The fields of the -.I fanotify_event_info_pidfd -structure are as follows: -.TP -.I hdr -This is a structure of type -.IR fanotify_event_info_header . -When an fanotify group is initialized using -.BR FAN_REPORT_PIDFD , -the -.I info_type -field value of the -.I fanotify_event_info_header -is set to -.BR FAN_EVENT_INFO_TYPE_PIDFD . -.TP -.I pidfd -This is a process file descriptor that refers to -the process responsible for generating the event. -The returned process file descriptor is no different from -one which could be obtained manually if -.BR pidfd_open (2) -were to be called on -.IR fanotify_event_metadata.pid . -In the instance that an error is encountered during pidfd creation, -one of two possible error types represented by -a negative integer value may be returned in this -.I pidfd -field. -In cases where -the process responsible for generating the event -has terminated prior to -the event listener being able to -read events from the notification queue, -.B FAN_NOPIDFD -is returned. -The pidfd creation for an event is only performed at the time the -events are read from the notification queue. -All other possible pidfd creation failures are represented by -.BR FAN_EPIDFD . -Once the event listener has dealt with an event -and the pidfd is no longer required, -the pidfd should be closed via -.BR close (2). -.P -The fields of the -.I fanotify_event_info_error -structure are as follows: -.TP -.I hdr -This is a structure of type -.IR fanotify_event_info_header . -The -.I info_type -field is set to -.BR FAN_EVENT_INFO_TYPE_ERROR . -.TP -.I error -Identifies the type of error that occurred. -.TP -.I error_count -This is a counter of the number of errors suppressed -since the last error was read. -.P -The following macros are provided to iterate over a buffer containing -fanotify event metadata returned by a -.BR read (2) -from an fanotify file descriptor: -.TP -.B FAN_EVENT_OK(meta, len) -This macro checks the remaining length -.I len -of the buffer -.I meta -against the length of the metadata structure and the -.I event_len -field of the first metadata structure in the buffer. -.TP -.B FAN_EVENT_NEXT(meta, len) -This macro uses the length indicated in the -.I event_len -field of the metadata structure pointed to by -.I meta -to calculate the address of the next metadata structure that follows -.IR meta . -.I len -is the number of bytes of metadata that currently remain in the buffer. -The macro returns a pointer to the next metadata structure that follows -.IR meta , -and reduces -.I len -by the number of bytes in the metadata structure that -has been skipped over (i.e., it subtracts -.I meta\->event_len -from -.IR len ). -.P -In addition, there is: -.TP -.B FAN_EVENT_METADATA_LEN -This macro returns the size (in bytes) of the structure -.IR fanotify_event_metadata . -This is the minimum size (and currently the only size) of any event metadata. -.\" -.SS Monitoring an fanotify file descriptor for events -When an fanotify event occurs, the fanotify file descriptor indicates as -readable when passed to -.BR epoll (7), -.BR poll (2), -or -.BR select (2). -.SS Dealing with permission events -For permission events, the application must -.BR write (2) -a structure of the following form to the -fanotify file descriptor: -.P -.in +4n -.EX -struct fanotify_response { - __s32 fd; - __u32 response; -}; -.EE -.in -.P -The fields of this structure are as follows: -.TP -.I fd -This is the file descriptor from the structure -.IR fanotify_event_metadata . -.TP -.I response -This field indicates whether or not the permission is to be granted. -Its value must be either -.B FAN_ALLOW -to allow the file operation or -.B FAN_DENY -to deny the file operation. -.P -If access is denied, the requesting application call will receive an -.B EPERM -error. -Additionally, if the notification group has been created with the -.B FAN_ENABLE_AUDIT -flag, then the -.B FAN_AUDIT -flag can be set in the -.I response -field. -In that case, the audit subsystem will log information about the access -decision to the audit logs. -.\" -.SS Monitoring filesystems for errors -A single -.B FAN_FS_ERROR -event is stored per filesystem at once. -Extra error messages are suppressed and accounted for in the -.I error_count -field of the existing -.B FAN_FS_ERROR -event record, -but details about the errors are lost. -.P -Errors reported by -.B FAN_FS_ERROR -are generic -.I errno -values, -but not all kinds of error types are reported by all filesystems. -.P -Errors not directly related to a file (i.e. super block corruption) -are reported with an invalid -.IR handle . -For these errors, the -.I handle -will have the field -.I handle_type -set to -.BR FILEID_INVALID , -and the handle buffer size set to -.BR 0 . -.\" -.SS Closing the fanotify file descriptor -When all file descriptors referring to the fanotify notification group are -closed, the fanotify group is released and its resources -are freed for reuse by the kernel. -Upon -.BR close (2), -outstanding permission events will be set to allowed. -.SS /proc interfaces -The file -.IR /proc/ pid /fdinfo/ fd -contains information about fanotify marks for file descriptor -.I fd -of process -.IR pid . -See -.BR proc (5) -for details. -.P -Since Linux 5.13, -.\" commit 5b8fea65d197f408bb00b251c70d842826d6b70b -the following interfaces can be used to control the amount of -kernel resources consumed by fanotify: -.TP -.I /proc/sys/fs/fanotify/max_queued_events -The value in this file is used when an application calls -.BR fanotify_init (2) -to set an upper limit on the number of events that can be -queued to the corresponding fanotify group. -Events in excess of this limit are dropped, but an -.B FAN_Q_OVERFLOW -event is always generated. -Prior to Linux kernel 5.13, -.\" commit 5b8fea65d197f408bb00b251c70d842826d6b70b -the hardcoded limit was 16384 events. -.TP -.I /proc/sys/fs/fanotify/max_user_group -This specifies an upper limit on the number of fanotify groups -that can be created per real user ID. -Prior to Linux kernel 5.13, -.\" commit 5b8fea65d197f408bb00b251c70d842826d6b70b -the hardcoded limit was 128 groups per user. -.TP -.I /proc/sys/fs/fanotify/max_user_marks -This specifies an upper limit on the number of fanotify marks -that can be created per real user ID. -Prior to Linux kernel 5.13, -.\" commit 5b8fea65d197f408bb00b251c70d842826d6b70b -the hardcoded limit was 8192 marks per group (not per user). -.SH ERRORS -In addition to the usual errors for -.BR read (2), -the following errors can occur when reading from the -fanotify file descriptor: -.TP -.B EINVAL -The buffer is too small to hold the event. -.TP -.B EMFILE -The per-process limit on the number of open files has been reached. -See the description of -.B RLIMIT_NOFILE -in -.BR getrlimit (2). -.TP -.B ENFILE -The system-wide limit on the total number of open files has been reached. -See -.I /proc/sys/fs/file\-max -in -.BR proc (5). -.TP -.B ETXTBSY -This error is returned by -.BR read (2) -if -.B O_RDWR -or -.B O_WRONLY -was specified in the -.I event_f_flags -argument when calling -.BR fanotify_init (2) -and an event occurred for a monitored file that is currently being executed. -.P -In addition to the usual errors for -.BR write (2), -the following errors can occur when writing to the fanotify file descriptor: -.TP -.B EINVAL -Fanotify access permissions are not enabled in the kernel configuration -or the value of -.I response -in the response structure is not valid. -.TP -.B ENOENT -The file descriptor -.I fd -in the response structure is not valid. -This may occur when a response for the permission event has already been -written. -.SH STANDARDS -Linux. -.SH HISTORY -The fanotify API was introduced in Linux 2.6.36 and -enabled in Linux 2.6.37. -fdinfo support was added in Linux 3.8. -.SH NOTES -The fanotify API is available only if the kernel was built with the -.B CONFIG_FANOTIFY -configuration option enabled. -In addition, fanotify permission handling is available only if the -.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS -configuration option is enabled. -.SS Limitations and caveats -Fanotify reports only events that a user-space program triggers through the -filesystem API. -As a result, -it does not catch remote events that occur on network filesystems. -.P -The fanotify API does not report file accesses and modifications that -may occur because of -.BR mmap (2), -.BR msync (2), -and -.BR munmap (2). -.P -Events for directories are created only if the directory itself is opened, -read, and closed. -Adding, removing, or changing children of a marked directory does not create -events for the monitored directory itself. -.P -Fanotify monitoring of directories is not recursive: -to monitor subdirectories under a directory, -additional marks must be created. -The -.B FAN_CREATE -event can be used for detecting when a subdirectory has been created under -a marked directory. -An additional mark must then be set on the newly created subdirectory. -This approach is racy, because it can lose events that occurred inside the -newly created subdirectory, before a mark is added on that subdirectory. -Monitoring mounts offers the capability to monitor a whole directory tree -in a race-free manner. -Monitoring filesystems offers the capability to monitor changes made from -any mount of a filesystem instance in a race-free manner. -.P -The event queue can overflow. -In this case, events are lost. -.SH BUGS -Before Linux 3.19, -.BR fallocate (2) -did not generate fanotify events. -Since Linux 3.19, -.\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35 -calls to -.BR fallocate (2) -generate -.B FAN_MODIFY -events. -.P -As of Linux 3.17, -the following bugs exist: -.IP \[bu] 3 -On Linux, a filesystem object may be accessible through multiple paths, -for example, a part of a filesystem may be remounted using the -.I \-\-bind -option of -.BR mount (8). -A listener that marked a mount will be notified only of events that were -triggered for a filesystem object using the same mount. -Any other event will pass unnoticed. -.IP \[bu] -.\" FIXME . A patch was proposed. -When an event is generated, -no check is made to see whether the user ID of the -receiving process has authorization to read or write the file -before passing a file descriptor for that file. -This poses a security risk, when the -.B CAP_SYS_ADMIN -capability is set for programs executed by unprivileged users. -.IP \[bu] -If a call to -.BR read (2) -processes multiple events from the fanotify queue and an error occurs, -the return value will be the total length of the events successfully -copied to the user-space buffer before the error occurred. -The return value will not be \-1, and -.I errno -will not be set. -Thus, the reading application has no way to detect the error. -.SH EXAMPLES -The two example programs below demonstrate the usage of the fanotify API. -.SS Example program: fanotify_example.c -The first program is an example of fanotify being -used with its event object information passed in the form of a file -descriptor. -The program marks the mount passed as a command-line argument and -waits for events of type -.B FAN_OPEN_PERM -and -.BR FAN_CLOSE_WRITE . -When a permission event occurs, a -.B FAN_ALLOW -response is given. -.P -The following shell session shows an example of -running this program. -This session involved editing the file -.IR /home/user/temp/notes . -Before the file was opened, a -.B FAN_OPEN_PERM -event occurred. -After the file was closed, a -.B FAN_CLOSE_WRITE -event occurred. -Execution of the program ends when the user presses the ENTER key. -.P -.in +4n -.EX -# \fB./fanotify_example /home\fP -Press enter key to terminate. -Listening for events. -FAN_OPEN_PERM: File /home/user/temp/notes -FAN_CLOSE_WRITE: File /home/user/temp/notes -\& -Listening for events stopped. -.EE -.in -.SS Program source: fanotify_example.c -\& -.EX -#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */ -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/fanotify.h> -#include <unistd.h> -\& -/* Read all available fanotify events from the file descriptor \[aq]fd\[aq]. */ -\& -static void -handle_events(int fd) -{ - const struct fanotify_event_metadata *metadata; - struct fanotify_event_metadata buf[200]; - ssize_t len; - char path[PATH_MAX]; - ssize_t path_len; - char procfd_path[PATH_MAX]; - struct fanotify_response response; -\& - /* Loop while events can be read from fanotify file descriptor. */ -\& - for (;;) { -\& - /* Read some events. */ -\& - len = read(fd, buf, sizeof(buf)); - if (len == \-1 && errno != EAGAIN) { - perror("read"); - exit(EXIT_FAILURE); - } -\& - /* Check if end of available data reached. */ -\& - if (len <= 0) - break; -\& - /* Point to the first event in the buffer. */ -\& - metadata = buf; -\& - /* Loop over all events in the buffer. */ -\& - while (FAN_EVENT_OK(metadata, len)) { -\& - /* Check that run\-time and compile\-time structures match. */ -\& - if (metadata\->vers != FANOTIFY_METADATA_VERSION) { - fprintf(stderr, - "Mismatch of fanotify metadata version.\en"); - exit(EXIT_FAILURE); - } -\& - /* metadata\->fd contains either FAN_NOFD, indicating a - queue overflow, or a file descriptor (a nonnegative - integer). Here, we simply ignore queue overflow. */ -\& - if (metadata\->fd >= 0) { -\& - /* Handle open permission event. */ -\& - if (metadata\->mask & FAN_OPEN_PERM) { - printf("FAN_OPEN_PERM: "); -\& - /* Allow file to be opened. */ -\& - response.fd = metadata\->fd; - response.response = FAN_ALLOW; - write(fd, &response, sizeof(response)); - } -\& - /* Handle closing of writable file event. */ -\& - if (metadata\->mask & FAN_CLOSE_WRITE) - printf("FAN_CLOSE_WRITE: "); -\& - /* Retrieve and print pathname of the accessed file. */ -\& - snprintf(procfd_path, sizeof(procfd_path), - "/proc/self/fd/%d", metadata\->fd); - path_len = readlink(procfd_path, path, - sizeof(path) \- 1); - if (path_len == \-1) { - perror("readlink"); - exit(EXIT_FAILURE); - } -\& - path[path_len] = \[aq]\e0\[aq]; - printf("File %s\en", path); -\& - /* Close the file descriptor of the event. */ -\& - close(metadata\->fd); - } -\& - /* Advance to next event. */ -\& - metadata = FAN_EVENT_NEXT(metadata, len); - } - } -} -\& -int -main(int argc, char *argv[]) -{ - char buf; - int fd, poll_num; - nfds_t nfds; - struct pollfd fds[2]; -\& - /* Check mount point is supplied. */ -\& - if (argc != 2) { - fprintf(stderr, "Usage: %s MOUNT\en", argv[0]); - exit(EXIT_FAILURE); - } -\& - printf("Press enter key to terminate.\en"); -\& - /* Create the file descriptor for accessing the fanotify API. */ -\& - fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK, - O_RDONLY | O_LARGEFILE); - if (fd == \-1) { - perror("fanotify_init"); - exit(EXIT_FAILURE); - } -\& - /* Mark the mount for: - \- permission events before opening files - \- notification events after closing a write\-enabled - file descriptor. */ -\& - if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, - FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD, - argv[1]) == \-1) { - perror("fanotify_mark"); - exit(EXIT_FAILURE); - } -\& - /* Prepare for polling. */ -\& - nfds = 2; -\& - fds[0].fd = STDIN_FILENO; /* Console input */ - fds[0].events = POLLIN; -\& - fds[1].fd = fd; /* Fanotify input */ - fds[1].events = POLLIN; -\& - /* This is the loop to wait for incoming events. */ -\& - printf("Listening for events.\en"); -\& - while (1) { - poll_num = poll(fds, nfds, \-1); - if (poll_num == \-1) { - if (errno == EINTR) /* Interrupted by a signal */ - continue; /* Restart poll() */ -\& - perror("poll"); /* Unexpected error */ - exit(EXIT_FAILURE); - } -\& - if (poll_num > 0) { - if (fds[0].revents & POLLIN) { -\& - /* Console input is available: empty stdin and quit. */ -\& - while (read(STDIN_FILENO, &buf, 1) > 0 && buf != \[aq]\en\[aq]) - continue; - break; - } -\& - if (fds[1].revents & POLLIN) { -\& - /* Fanotify events are available. */ -\& - handle_events(fd); - } - } - } -\& - printf("Listening for events stopped.\en"); - exit(EXIT_SUCCESS); -} -.EE -.\" -.SS Example program: fanotify_fid.c -The second program is an example of fanotify being used with a group that -identifies objects by file handles. -The program marks the filesystem object that is passed as -a command-line argument -and waits until an event of type -.B FAN_CREATE -has occurred. -The event mask indicates which type of filesystem object\[em]either -a file or a directory\[em]was created. -Once all events have been read from the buffer and processed accordingly, -the program simply terminates. -.P -The following shell sessions show two different invocations of -this program, with different actions performed on a watched object. -.P -The first session shows a mark being placed on -.IR /home/user . -This is followed by the creation of a regular file, -.IR /home/user/testfile.txt . -This results in a -.B FAN_CREATE -event being generated and reported against the file's parent watched -directory object and with the created file name. -Program execution ends once all events captured within the buffer have -been processed. -.P -.in +4n -.EX -# \fB./fanotify_fid /home/user\fP -Listening for events. -FAN_CREATE (file created): - Directory /home/user has been modified. - Entry \[aq]testfile.txt\[aq] is not a subdirectory. -All events processed successfully. Program exiting. -\& -$ \fBtouch /home/user/testfile.txt\fP # In another terminal -.EE -.in -.P -The second session shows a mark being placed on -.IR /home/user . -This is followed by the creation of a directory, -.IR /home/user/testdir . -This specific action results in a -.B FAN_CREATE -event being generated and is reported with the -.B FAN_ONDIR -flag set and with the created directory name. -.P -.in +4n -.EX -# \fB./fanotify_fid /home/user\fP -Listening for events. -FAN_CREATE | FAN_ONDIR (subdirectory created): - Directory /home/user has been modified. - Entry \[aq]testdir\[aq] is a subdirectory. -All events processed successfully. Program exiting. -\& -$ \fBmkdir \-p /home/user/testdir\fP # In another terminal -.EE -.in -.SS Program source: fanotify_fid.c -\& -.EX -#define _GNU_SOURCE -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/fanotify.h> -#include <unistd.h> -\& -#define BUF_SIZE 256 -\& -int -main(int argc, char *argv[]) -{ - int fd, ret, event_fd, mount_fd; - ssize_t len, path_len; - char path[PATH_MAX]; - char procfd_path[PATH_MAX]; - char events_buf[BUF_SIZE]; - struct file_handle *file_handle; - struct fanotify_event_metadata *metadata; - struct fanotify_event_info_fid *fid; - const char *file_name; - struct stat sb; -\& - if (argc != 2) { - fprintf(stderr, "Invalid number of command line arguments.\en"); - exit(EXIT_FAILURE); - } -\& - mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY); - if (mount_fd == \-1) { - perror(argv[1]); - exit(EXIT_FAILURE); - } -\& - /* Create an fanotify file descriptor with FAN_REPORT_DFID_NAME as - a flag so that program can receive fid events with directory - entry name. */ -\& - fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, 0); - if (fd == \-1) { - perror("fanotify_init"); - exit(EXIT_FAILURE); - } -\& - /* Place a mark on the filesystem object supplied in argv[1]. */ -\& - ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR, - FAN_CREATE | FAN_ONDIR, - AT_FDCWD, argv[1]); - if (ret == \-1) { - perror("fanotify_mark"); - exit(EXIT_FAILURE); - } -\& - printf("Listening for events.\en"); -\& - /* Read events from the event queue into a buffer. */ -\& - len = read(fd, events_buf, sizeof(events_buf)); - if (len == \-1 && errno != EAGAIN) { - perror("read"); - exit(EXIT_FAILURE); - } -\& - /* Process all events within the buffer. */ -\& - for (metadata = (struct fanotify_event_metadata *) events_buf; - FAN_EVENT_OK(metadata, len); - metadata = FAN_EVENT_NEXT(metadata, len)) { - fid = (struct fanotify_event_info_fid *) (metadata + 1); - file_handle = (struct file_handle *) fid\->handle; -\& - /* Ensure that the event info is of the correct type. */ -\& - if (fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_FID || - fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) { - file_name = NULL; - } else if (fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) { - file_name = file_handle\->f_handle + - file_handle\->handle_bytes; - } else { - fprintf(stderr, "Received unexpected event info type.\en"); - exit(EXIT_FAILURE); - } -\& - if (metadata\->mask == FAN_CREATE) - printf("FAN_CREATE (file created):\en"); -\& - if (metadata\->mask == (FAN_CREATE | FAN_ONDIR)) - printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\en"); -\& - /* metadata\->fd is set to FAN_NOFD when the group identifies - objects by file handles. To obtain a file descriptor for - the file object corresponding to an event you can use the - struct file_handle that\[aq]s provided within the - fanotify_event_info_fid in conjunction with the - open_by_handle_at(2) system call. A check for ESTALE is - done to accommodate for the situation where the file handle - for the object was deleted prior to this system call. */ -\& - event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY); - if (event_fd == \-1) { - if (errno == ESTALE) { - printf("File handle is no longer valid. " - "File has been deleted\en"); - continue; - } else { - perror("open_by_handle_at"); - exit(EXIT_FAILURE); - } - } -\& - snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", - event_fd); -\& - /* Retrieve and print the path of the modified dentry. */ -\& - path_len = readlink(procfd_path, path, sizeof(path) \- 1); - if (path_len == \-1) { - perror("readlink"); - exit(EXIT_FAILURE); - } -\& - path[path_len] = \[aq]\e0\[aq]; - printf("\etDirectory \[aq]%s\[aq] has been modified.\en", path); -\& - if (file_name) { - ret = fstatat(event_fd, file_name, &sb, 0); - if (ret == \-1) { - if (errno != ENOENT) { - perror("fstatat"); - exit(EXIT_FAILURE); - } - printf("\etEntry \[aq]%s\[aq] does not exist.\en", file_name); - } else if ((sb.st_mode & S_IFMT) == S_IFDIR) { - printf("\etEntry \[aq]%s\[aq] is a subdirectory.\en", file_name); - } else { - printf("\etEntry \[aq]%s\[aq] is not a subdirectory.\en", - file_name); - } - } -\& - /* Close associated file descriptor for this event. */ -\& - close(event_fd); - } -\& - printf("All events processed successfully. Program exiting.\en"); - exit(EXIT_SUCCESS); -} -.EE -.SH SEE ALSO -.ad l -.BR fanotify_init (2), -.BR fanotify_mark (2), -.BR inotify (7) |