Eric, Another ping for this request. Could you please take a look at the fanotify man pages that Heinrich has written. Cheers, Michael On Wed, May 7, 2014 at 9:15 PM, Michael Kerrisk (man-pages) <mtk.manpages@xxxxxxxxx> wrote: > Hello Eric, > > Ping for this request. Could you please take a look at these pages? > > Thanks, > > Michael > > > > On Tue, Apr 29, 2014 at 3:51 PM, Michael Kerrisk (man-pages) > <mtk.manpages@xxxxxxxxx> wrote: >> Hello Eric (and all), >> >> Heinrich Schuchardt has made a magnificent effort writing some man >> pages that extensively document the fanotify API that you added in >> Linux 2.6.36/37. Could I ask you (and anyone else who is interested) >> to review them please for completeness and accuracy. I would >> really like to get such a review before publishing the pages, in >> order to minimize the chance of publishing errors >> >> The pages are: >> >> fanotify.7: >> An overview of the fanotify API complete with an >> example program, n >> >> fanotify_init.2 >> Description of the fanotify_init() system call >> >> fanotify_mark.2 >> Description of the fanotify_mark() system call >> >> Cheers, >> >> Michael >> >> >> >> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2 >> new file mode 100644 >> index 0000000..e54fe7e >> --- /dev/null >> +++ b/man2/fanotify_init.2 >> @@ -0,0 +1,206 @@ >> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@xxxxxx> >> +.\" >> +.\" %%%LICENSE_START(VERBATIM) >> +.\" Permission is granted to make and distribute verbatim copies of this >> +.\" manual provided the copyright notice and this permission notice are >> +.\" preserved on all copies. >> +.\" >> +.\" Permission is granted to copy and distribute modified versions of >> +.\" this manual under the conditions for verbatim copying, provided that >> +.\" the entire resulting derived work is distributed under the terms of >> +.\" a permission notice identical to this one. >> +.\" >> +.\" Since the Linux kernel and libraries are constantly changing, this >> +.\" manual page may be incorrect or out-of-date. The author(s) assume. >> +.\" no responsibility for errors or omissions, or for damages resulting. >> +.\" from the use of the information contained herein. The author(s) may. >> +.\" not have taken the same level of care in the production of this. >> +.\" manual, which is licensed free of charge, as they might when working. >> +.\" professionally. >> +.\" >> +.\" Formatted or processed versions of this manual, if unaccompanied by >> +.\" the source, must acknowledge the copyright and authors of this work. >> +.\" %%%LICENSE_END >> +.TH FANOTIFY_INIT 2 2014-04-24 "Linux" "Linux Programmer's Manual" >> +.SH NAME >> +fanotify_init \- create and initialize fanotify group >> +.SH SYNOPSIS >> +.B #include <fcntl.h> >> +.br >> +.B #include <sys/fanotify.h> >> +.sp >> +.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags ); >> +.SH DESCRIPTION >> +For an overview of the fanotify API, see >> +.BR fanotify (7). >> +.PP >> +.BR fanotify_init () >> +initializes a new fanotify group and returns a file descriptor for the event >> +queue associated with the group. >> +.PP >> +The file descriptor is used in calls to >> +.BR fanotify_mark (2) >> +to specify the files, directories, and mounts for which fanotify events shall >> +be created. >> +These events are received by reading from the file descriptor. >> +Some events are only informative, indicating that a file has been accessed. >> +Other events can be used to determine whether >> +another application is permitted to access a file or directory. >> +Permission to access filesystem objects is granted by writing to the file >> +descriptor. >> +.PP >> +Multiple programs may be using the fanotify interface at the same time to >> +monitor the same files. >> +.PP >> +In the current implementation, the number of fanotify groups per user is >> +limited to 128. >> +This limit cannot be overridden. >> +.PP >> +Calling >> +.BR fanotify_init () >> +requires the >> +.B CAP_SYS_ADMIN >> +capability. >> +This constraint might be relaxed in future versions of the API. >> +Therefore, certain additional capability checks have been implemented as >> +indicated below. >> +.PP >> +The >> +.I flags >> +argument contains a multi-bit field defining the notification class of the >> +listening application and further single bit fields specifying the behavior of >> +the file descriptor. >> +.PP >> +If multiple listeners for permission events exist, the notification class is >> +used to establish the sequence in which the listeners receive the events. >> +.PP >> +Only one of the following notification classes may be specified in >> +.IR flags : >> +.TP >> +.B FAN_CLASS_PRE_CONTENT >> +This value allows the receipt of events notifying that a file has been >> +accessed and events for permission decisions if a file may be accessed. >> +It is intended for event listeners that need to access files before they >> +contain their final data. >> +This notification class might be used by hierarchical storage managers, for >> +example. >> +.TP >> +.B FAN_CLASS_CONTENT >> +This value allows the receipt of events notifying that a file has been >> +accessed and events for permission decisions if a file may be accessed. >> +It is intended for event listeners that need to access files when they already >> +contain their final content. >> +This notification class might be used by malware detection programs, for >> +example. >> +.TP >> +.B FAN_CLASS_NOTIF >> +This is the default value. >> +It does not need to be specified. >> +This value only allows the receipt of events notifying that a file has been >> +accessed. >> +Permission decisions before the file is accessed are not possible. >> +.PP >> +Listeners with different notification classes will receive events in the >> +order >> +.BR FAN_CLASS_PRE_CONTENT , >> +.BR FAN_CLASS_CONTENT , >> +.BR FAN_CLASS_NOTIF . >> +The order of notification for listeners of the same value is undefined. >> +.PP >> +The following bit mask values can be set additionally in >> +.IR flags : >> +.TP >> +.B FAN_CLOEXEC >> +This flag sets the close-on-exec flag >> +.RB ( FD_CLOEXEC ) >> +on the new file descriptor. >> +See the description of the >> +.B O_CLOEXEC >> +flag in >> +.BR open (2). >> +.TP >> +.B FAN_NONBLOCK >> +This flag enables the nonblocking flag >> +.RB ( O_NONBLOCK ) >> +for the file descriptor. >> +Reading from the file descriptor will not block. >> +Instead, if no data is available, >> +.BR read (2) >> +will fail with the error >> +.BR EAGAIN . >> +.TP >> +.B FAN_UNLIMITED_QUEUE >> +This flag removes the limit of 16384 events for the event queue. >> +It requires the >> +.B CAP_SYS_ADMIN >> +capability. >> +.TP >> +.B FAN_UNLIMITED_MARKS >> +This flag removes the limit of 8192 marks. >> +It requires the >> +.B CAP_SYS_ADMIN >> +capability. >> +.PP >> +The argument >> +.I event_f_flags >> +defines the file flags with which file descriptors for fanotify events shall >> +be created. >> +For explanations of possible values, see the argument >> +.I flags >> +of the >> +.BR open (2) >> +system call. >> +Useful values are: >> +.TP >> +.B O_RDONLY >> +This value allows only read access. >> +.TP >> +.B O_WRONLY >> +This value allows only write access. >> +.TP >> +.B O_RDWR >> +This value allows read and write access. >> +.TP >> +.B O_CLOEXEC >> +This flag enables the close-on-exec flag for the file descriptor. >> +.TP >> +.B O_LARGEFILE >> +This flag enables support for files exceeding 2 GB. >> +Failing to set this flag will result in an >> +.B EOVERFLOW >> +error when trying to open a large file which is monitored by an fanotify group >> +on a 32-bit system. >> +.SH RETURN VALUE >> +On success, >> +.BR fanotify_init () >> +returns a new file descriptor. >> +On error, \-1 is returned, and >> +.I errno >> +is set to indicate the error. >> +.SH ERRORS >> +.TP >> +.B EINVAL >> +An invalid value was passed in >> +.IR flags . >> +.B FAN_ALL_INIT_FLAGS >> +defines all allowable bits. >> +.TP >> +.B EMFILE >> +The number of fanotify groups of the user exceeds 128. >> +.TP >> +.B ENOMEM >> +The allocation of memory for the notification group failed. >> +.TP >> +.B EPERM >> +The operation is not permitted because the caller lacks the >> +.B CAP_SYS_ADMIN >> +capability. >> +.SH VERSIONS >> +.BR fanotify_init () >> +was introduced in version 2.6.36 of the Linux kernel and enabled in version >> +2.6.37. >> +.SH "CONFORMING TO" >> +This system call is Linux-specific. >> +.SH "SEE ALSO" >> +.BR fanotify_mark (2), >> +.BR fanotify (7) >> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2 >> new file mode 100644 >> index 0000000..693eff8 >> --- /dev/null >> +++ b/man2/fanotify_mark.2 >> @@ -0,0 +1,327 @@ >> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@xxxxxx> >> +.\" >> +.\" %%%LICENSE_START(VERBATIM) >> +.\" Permission is granted to make and distribute verbatim copies of this >> +.\" manual provided the copyright notice and this permission notice are >> +.\" preserved on all copies. >> +.\" >> +.\" Permission is granted to copy and distribute modified versions of >> +.\" this manual under the conditions for verbatim copying, provided that >> +.\" the entire resulting derived work is distributed under the terms of >> +.\" a permission notice identical to this one. >> +.\" >> +.\" Since the Linux kernel and libraries are constantly changing, this >> +.\" manual page may be incorrect or out-of-date. The author(s) assume. >> +.\" no responsibility for errors or omissions, or for damages resulting. >> +.\" from the use of the information contained herein. The author(s) may. >> +.\" not have taken the same level of care in the production of this. >> +.\" manual, which is licensed free of charge, as they might when working. >> +.\" professionally. >> +.\" >> +.\" Formatted or processed versions of this manual, if unaccompanied by >> +.\" the source, must acknowledge the copyright and authors of this work. >> +.\" %%%LICENSE_END >> +.TH FANOTIFY_MARK 2 2014-04-24 "Linux" "Linux Programmer's Manual" >> +.SH NAME >> +fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem >> +object >> +.SH SYNOPSIS >> +.nf >> +.B #include <sys/fanotify.h> >> +.sp >> +.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags , >> +.BI " uint64_t " mask ", int " dirfd \ >> +", const char *" pathname ); >> +.fi >> +.SH DESCRIPTION >> +For an overview of the fanotify API, see >> +.BR fanotify (7). >> +.PP >> +.BR fanotify_mark (2) >> +adds, removes, or modifies an fanotify mark on a filesystem object. >> +The caller must have read permission on the filesystem object that is to be >> +marked. >> +.PP >> +The >> +.I fanotify_fd >> +argument is a file descriptor returned by >> +.BR fanotify_init (2). >> +.PP >> +.I flags >> +is a bit mask describing the modification to perform. >> +It must include exactly one of the following values: >> +.TP >> +.B FAN_MARK_ADD >> +The events in >> +.I mask >> +will be added to the mark mask (or to the ignore mask). >> +.I mask >> +must be nonempty or the error >> +.B EINVAL >> +will occur. >> +.TP >> +.B FAN_MARK_REMOVE >> +The events in argument >> +.I mask >> +will be removed from the mark mask (or from the ignore mask). >> +.I mask >> +must be nonempty or the error >> +.B EINVAL >> +will occur. >> +.TP >> +.B FAN_MARK_FLUSH >> +Remove either all mount or non-mount marks from the fanotify group. >> +If >> +.I flag >> +contains >> +.BR FAN_MARK_MOUNT , >> +all marks for mounts are removed from the group. >> +Otherwise, all marks for directories and files are removed. >> +No flag other than >> +.B FAN_MARK_MOUNT >> +can be used in conjunction with >> +.BR FAN_MARK_FLUSH . >> +.I mask >> +is ignored. >> +.PP >> +If none of the values above is specified, or more than one is specified, the >> +call fails with the error >> +.BR EINVAL . >> +.PP >> +In addition, >> +.I flags >> +may contain zero or more of the following: >> +.TP >> +.B FAN_MARK_DONT_FOLLOW >> +If >> +.I pathname >> +is a symbolic link, mark the link itself, rather than the file to which it >> +refers. >> +(By default, >> +.BR fanotify_mark () >> +dereferences >> +.I pathname >> +if it is a symbolic link.) >> +.TP >> +.B FAN_MARK_ONLYDIR >> +If the filesystem object to be marked is not a directory, the error >> +.B ENOTDIR >> +shall be raised. >> +.TP >> +.B FAN_MARK_MOUNT >> +Mark the mount point specified by >> +.IR pathname . >> +If >> +.I pathname >> +is not itself a mount point, the mount point containing >> +.I pathname >> +will be marked. >> +All directories, subdirectories, and the contained files of the mount point >> +will be monitored. >> +.TP >> +.B FAN_MARK_IGNORED_MASK >> +The events in >> +.I mask >> +shall be added to or removed from the ignore mask. >> +.TP >> +.B FAN_MARK_IGNORED_SURV_MODIFY >> +The ignore mask shall survive modify events. >> +If this flag is not set, the ignore mask is cleared when a modify event occurs >> +for the ignored file or directory. >> +.PP >> +.I mask >> +defines which events shall be listened to (or which shall be ignored). >> +It is a bit mask composed of the following values: >> +.TP >> +.B FAN_ACCESS >> +Create an event when a file or directory (but see BUGS) is accessed (read). >> +.TP >> +.B FAN_MODIFY >> +Create an event when a file is modified (write). >> +.TP >> +.B FAN_CLOSE_WRITE >> +Create an event when a writable file is closed. >> +.TP >> +.B FAN_CLOSE_NOWRITE >> +Create an event when a read-only file or directory is closed. >> +.TP >> +.B FAN_OPEN >> +Create an event when a file or directory is opened. >> +.TP >> +.B FAN_OPEN_PERM >> +Create an event when a permission to open a file or directory is requested. >> +An fanotify file descriptor created with >> +.B FAN_CLASS_PRE_CONTENT >> +or >> +.B FAN_CLASS_CONTENT >> +is required. >> +.TP >> +.B FAN_ACCESS_PERM >> +Create an event when a permission to read a file or directory is requested. >> +An fanotify file descriptor created with >> +.B FAN_CLASS_PRE_CONTENT >> +or >> +.B FAN_CLASS_CONTENT >> +is required. >> +.TP >> +.B FAN_ONDIR >> +Events for directories shall be created, for example when >> +.BR opendir (2), >> +.BR readdir (2) >> +(but see BUGS), and >> +.BR closedir (2) >> +are called. >> +Without this flag, only events for files are created. >> +.TP >> +.B FAN_EVENT_ON_CHILD >> +Events for the immediate children of marked directories shall be created. >> +The flag has no effect when marking mounts. >> +Note that events are not generated for children of the subdirectories >> +of marked directories. >> +To monitor complete directory trees it is necessary to mark the relevant >> +mount. >> +.PP >> +The following composed value is defined: >> +.TP >> +.B FAN_CLOSE >> +A file is closed >> +.RB ( FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE ). >> +.PP >> +The filesystem object to be marked is determined by the file descriptor >> +.I dirfd >> +and the pathname specified in >> +.IR pathname : >> +.IP * 3 >> +If >> +.I pathname >> +is NULL, >> +.I dirfd >> +defines the filesystem object to be marked. >> +.IP * >> +If >> +.I pathname >> +is NULL, and >> +.I dirfd >> +takes the special value >> +.BR AT_FDCWD , >> +the current working directory is to be marked. >> +.IP * >> +If >> +.I pathname >> +is absolute, it defines the filesystem object to be marked, and >> +.I dirfd >> +is ignored. >> +.IP * >> +If >> +.I pathname >> +is relative, and >> +.I dirfd >> +does not have the value >> +.BR AT_FDCWD , >> +then the filesystem object to be marked is determined by interpreting >> +.I pathname >> +relative the directory referred to by >> +.IR dirfd . >> +.IP * >> +If >> +.I pathname >> +is relative, and >> +.I dirfd >> +has the value >> +.BR AT_FDCWD, >> +then the filesystem object to be marked is determined by interpreting >> +.I pathname >> +relative the current working directory. >> +.SH RETURN VALUE >> +On success, >> +.BR fanotify_mark () >> +returns 0. >> +On error, \-1 is returned, and >> +.I errno >> +is set to indicate the error. >> +.SH ERRORS >> +.TP >> +.B EBADF >> +An invalid file descriptor was passed in >> +.IR fanotify_fd . >> +.TP >> +.B EINVAL >> +An invalid value was passed in >> +.IR flags >> +or >> +.IR mask , >> +or >> +.I fanotify_fd >> +was not an fanotify file descriptor. >> +.TP >> +.B EINVAL >> +The fanotify file descriptor was opened with >> +.B FAN_CLASS_NOTIF >> +and mask contains a flag for permission events >> +.RB ( FAN_OPEN_PERM >> +or >> +.BR FAN_ACCESS_PERM ). >> +.TP >> +.B ENOENT >> +The filesystem object indicated by >> +.IR dirfd >> +and >> +.IR pathname >> +does not exist. >> +This error also occurs when trying to remove a mark from an object which is not >> +marked. >> +.TP >> +.B ENOMEM >> +The necessary memory could not be allocated. >> +.TP >> +.B ENOSPC >> +The number of marks exceeds the limit of 8192 and >> +.B FAN_UNLIMITED_MARKS >> +was not specified in the call to >> +.BR fanotify_init (2). >> +.TP >> +.B ENOTDIR >> +.I flags >> +contains >> +.BR FAN_MARK_ONLYDIR , >> +and >> +.I dirfd >> +and >> +.I pathname >> +do not specify a directory. >> +.SH VERSIONS >> +.BR fanotify_mark () >> +was introduced in version 2.6.36 of the Linux kernel and enabled in version >> +2.6.37. >> +.SH CONFORMING TO >> +This system call is Linux-specific. >> +.SH BUGS >> +As of Linux 3.15, >> +the following bugs exist: >> +.IP * 3 >> +.\" FIXME: Patch is in next-20140424. >> +If >> +.I flags >> +contains >> +.BR FAN_MARK_FLUSH , >> +.I dfd >> +and >> +.I pathname >> +must indicate a filesystem object, even though this object is not used. >> +.IP * >> +.\" FIXME: Patch is in next-20140424. >> +.BR readdir (2) >> +does not result in a >> +.B FAN_ACCESS >> +event. >> +.IP * >> +.\" FIXME: Patch proposed. >> +If >> +.BR fanotify_mark (2) >> +is called with >> +.B FAN_MARK_FLUSH, >> +.I flags >> +is not checked for invalid values. >> +.SH SEE ALSO >> +.BR fanotify_init (2), >> +.BR fanotify (7) >> diff --git a/man7/fanotify.7 b/man7/fanotify.7 >> new file mode 100644 >> index 0000000..083244f >> --- /dev/null >> +++ b/man7/fanotify.7 >> @@ -0,0 +1,684 @@ >> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@xxxxxx> >> +.\" >> +.\" %%%LICENSE_START(VERBATIM) >> +.\" Permission is granted to make and distribute verbatim copies of this >> +.\" manual provided the copyright notice and this permission notice are >> +.\" preserved on all copies. >> +.\" >> +.\" Permission is granted to copy and distribute modified versions of >> +.\" this manual under the conditions for verbatim copying, provided that >> +.\" the entire resulting derived work is distributed under the terms of >> +.\" a permission notice identical to this one. >> +.\" >> +.\" Since the Linux kernel and libraries are constantly changing, this >> +.\" manual page may be incorrect or out-of-date. The author(s) assume. >> +.\" no responsibility for errors or omissions, or for damages resulting. >> +.\" from the use of the information contained herein. The author(s) may. >> +.\" not have taken the same level of care in the production of this. >> +.\" manual, which is licensed free of charge, as they might when working. >> +.\" professionally. >> +.\" >> +.\" Formatted or processed versions of this manual, if unaccompanied by >> +.\" the source, must acknowledge the copyright and authors of this work. >> +.\" %%%LICENSE_END >> +.TH FANOTIFY 7 2014-04-24 "Linux" "Linux Programmer's Manual" >> +.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. >> +Currently, only a limited set of events is supported. >> +In particular, there is no support for create, delete, and move events. >> +(See >> +.BR inotify (7) >> +for details of an API that does notify those events.) >> + >> +Additional capabilities compared to the >> +.BR inotify (7) >> +API are monitoring of complete mounts, access permission decisions, and the >> +possibility to read or modify files before access by other applications. >> + >> +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. >> +.PP >> +An fanotify notification group is a kernel-internal object that holds >> +a list of files, directories, and mount points for which events shall be >> +created. >> +.PP >> +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 mount point or directory to be >> +marked for receiving events, while at the same time ignoring events for >> +specific objects under that mount point or directory. >> +.PP >> +The >> +.BR fanotify_mark (2) >> +system call adds a file, directory, or mount to a notification group >> +and specifies which events >> +shall be reported (or ignored), or removes or modifies such an entry. >> +.PP >> +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 point 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 closed event, the modify event can be removed from the >> +ignore mask and the file cache entry can be updated. >> +.PP >> +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, the respective entries survive. >> +If files or directories are deleted or mounts are unmounted, the corresponding >> +entries are deleted. >> +.SS The event queue >> +As events occur on the filesystem objects monitired 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). >> + >> +Two types of events are generated: >> +notification events and permission events. >> +Notification events are merely informative >> +and require no action to be taken by >> +the receiving application except for closing the file descriptor passed in the >> +event. >> +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. >> + >> +Queue entries for notification events are removed when the event has been >> +read. >> +Queue entries for permission events are removed when the permission >> +decision has been taken by writing to the fanotify file descriptor. >> +.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)). >> + >> +The return value of >> +.BR read (2) >> +is the length of the filled buffer, or \-1 in case of an error. >> +After a successful >> +.BR read (2), >> +the read buffer contains one or more of the following structures: >> + >> +.in +4n >> +.nf >> +struct fanotify_event_metadata { >> + __u32 event_len; >> + __u8 vers; >> + __u8 reserved; >> + __u16 metadata_len; >> + __aligned_u64 mask; >> + __s32 fd; >> + __s32 pid; >> +}; >> +.fi >> +.in >> +.PP >> +The fields of this structure 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. >> +In the current implementation, the value of >> +.I event_len >> +is always >> +.BR FAN_EVENT_METADATA_LEN . >> +In principle, the API design would allow to return variable-length structures. >> +Therefore, and for performance reasons, it is recommended to use a larger >> +buffer size when reading, for example 4096 bytes. >> +.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 runtime 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. >> +.TP >> +.I fd >> +This is an open file descriptor for the object being accessed, or >> +.B FAN_NOFD >> +if a queue overflow occurred. >> +The file descriptor can be used to access the contents of the monitored file or >> +directory. >> +The >> +.B FMODE_NONOTIFY >> +file status flag is set on the corresponding 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. >> +The reading application is responsible for closing the file descriptor. >> +.TP >> +.I pid >> +This is the ID of the process that caused the event. >> +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 program. >> +.PP >> +The bit mask in >> +.I mask >> +signals 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 obect. >> +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. >> +.PP >> +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_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 of 16384 entries. >> +This limit can be overridden in the call to >> +.BR fanotify_init (2) >> +by setting the flag >> +.BR FAN_UNLIMITED_QUEUE . >> +.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 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. >> +.PP >> +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; >> + >> + FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE >> +.PP >> +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 sets the pointer >> +.I meta >> +to the next metadata structure using the length indicated in the >> +.I event_len >> +field of the metadata structure and reduces the remaining length of the >> +buffer >> +.IR len . >> +.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: >> + >> +.in +4n >> +.nf >> +struct fanotify_response { >> + __s32 fd; >> + __u32 response; >> +}; >> +.fi >> +.in >> +.PP >> +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. >> +.PP >> +If access is denied, the requesting application call will receive an >> +.BR EPERM >> +error. >> +.SS Closing the fanotify file descriptor >> +.PP >> +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/[pid]/fdinfo >> +The file >> +.I /proc/[pid]/fdinfo/[fd] >> +contains information about fanotify marks for file descriptor >> +.I fd >> +of process >> +.IR pid . >> +See the kernel source file >> +.I Documentation/filesystems/proc.txt >> +for details. >> +.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 short 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 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. >> +.PP >> +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 might occur because the file was already deleted by another thread or >> +process. >> +.SH VERSIONS >> +The fanotify API was introduced in version 2.6.36 of the Linux kernel and >> +enabled in version 2.6.37. >> +Fdinfo support was added in version 3.8. >> +.SH "CONFORMING TO" >> +The fanotify API is Linux-specific. >> +.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. >> +.PP >> +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). >> +.PP >> +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. >> +.PP >> +Fanotify monitoring of directories is not recursive: to monitor subdirectories >> +under a directory, additional marks must be created. >> +(But note that the fanotify API provides no way of detecting when a >> +subdirectory has been created under a marked directory, which makes recursive >> +monitoring difficult.) >> +Monitoring mounts offers the capability to monitor a whole directory tree. >> +.PP >> +The event queue can overflow. >> +In this case, events are lost. >> +.SH BUGS >> +As of Linux 3.15, >> +the following bug exists: >> +.IP * 3 >> +.\" 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. >> +.SH EXAMPLE >> +The following program demonstrates the usage of the fanotify API. >> +It marks the mount point passed as command-line argument >> +and waits for events of type >> +.B FAN_PERM_OPEN >> +and >> +.BR FAN_CLOSE_WRITE . >> +When a permission event occurs, a >> +.B FAN_ALLOW >> +response is given. >> +.PP >> +The following output was recorded while 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. >> +.SS Example output >> +.in +4n >> +.nf >> +# ./fanotify_example /home >> +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. >> +.fi >> +.in >> +.SS Program source >> +.nf >> +#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 'fd' */ >> + >> +static void >> +handle_events(int fd) >> +{ >> + const struct fanotify_event_metadata *metadata; >> + char buf[4096]; >> + 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, (void *) &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 = (struct fanotify_event_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.\\n"); >> + 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(struct fanotify_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] = '\\0'; >> + printf("File %s\\n", 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\\n", argv[0]); >> + exit(EXIT_FAILURE); >> + } >> + >> + printf("Press enter key to terminate.\\n"); >> + >> + /* 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, \-1, >> + argv[1]) == \-1) { >> + perror("fanotify_mark"); >> + exit(EXIT_FAILURE); >> + } >> + >> + /* Prepare for polling */ >> + >> + nfds = 2; >> + >> + /* Console input */ >> + >> + fds[0].fd = STDIN_FILENO; >> + fds[0].events = POLLIN; >> + >> + /* Fanotify input */ >> + >> + fds[1].fd = fd; >> + fds[1].events = POLLIN; >> + >> + /* This is the loop to wait for incoming events */ >> + >> + printf("Listening for events.\\n"); >> + >> + 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 != '\\n') >> + continue; >> + break; >> + } >> + >> + if (fds[1].revents & POLLIN) { >> + >> + /* Fanotify events are available */ >> + >> + handle_events(fd); >> + } >> + } >> + } >> + >> + printf("Listening for events stopped.\\n"); >> + exit(EXIT_SUCCESS); >> +} >> +.fi >> +.SH "SEE ALSO" >> +.ad l >> +.BR fanotify_init (2), >> +.BR fanotify_mark (2), >> +.BR inotify (7) >> >> -- >> Michael Kerrisk >> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ >> Linux/UNIX System Programming Training: http://man7.org/training/ > > > > -- > Michael Kerrisk > Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ > Linux/UNIX System Programming Training: http://man7.org/training/ -- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Linux/UNIX System Programming Training: http://man7.org/training/ -- To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html