Hello Michael, I applied all you request for changes, including the example code. For fanotify_mark(2) you did not review the latest version: It is flags and not mask that is not yet properly checked. ' I think that last sentence could go. FAN_ALL_INIT_FLAGS is non it sys/fanotify.h ' (only in the linux/ header file). The definition of FAN_ALL_INIT_FLAGS is in /include/uapi/linux/fanotify.h like FAN_CLOEXEC. Hence, it is also available in sys/fanotify.h In a prior mail you wrote: ' ' +This length might be longer than the size of structure ' ' +.I fanotify_event_metadata. ' ' .IR fanotify_event_metadata . ' ' Also, here, I think you need to add a few words about *why* it might be longer. ' Otherwise the reader is left puzzled. (The *why* could eb a forward reference ' to some explanatory text lower in the page.) I reworked the paragraph. Best regards Heinrich Signed-off-by: Heinrich Schuchardt <xypron.glpk@xxxxxx> --- man2/fanotify_init.2 | 207 ++++++++++++++++ man2/fanotify_mark.2 | 327 +++++++++++++++++++++++++ man7/fanotify.7 | 670 +++++++++++++++++++++++++++++++++++++++++++++++++++ man7/inotify.7 | 3 +- 4 files changed, 1206 insertions(+), 1 deletion(-) create mode 100644 man2/fanotify_init.2 create mode 100644 man2/fanotify_mark.2 create mode 100644 man7/fanotify.7 diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2 new file mode 100644 index 0000000..3214d9e --- /dev/null +++ b/man2/fanotify_init.2 @@ -0,0 +1,207 @@ +.\" 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 control if another application may 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 values 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 +sequence +.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 in a call to +.BR read (2) +the error +.B EAGAIN +will occur. +.TP +.B FAN_UNLIMITED_QUEUE +This flag removes the limit of 16384 events on the size of 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. +In case of an 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..2975f4b --- /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 , +.BI " 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. +.PP +The caller must have read permission on the filesystem object that is to be +marked. +.PP +The +.I fanotify_fd +argument is the 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 other flag but +.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 +The +.I pathname +indicates a mount point to be marked. +If the path is not itself a mount point, the mount point containing the path +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. +In case of an 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 valid path. +This path 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..efb20bb --- /dev/null +++ b/man7/fanotify.7 @@ -0,0 +1,670 @@ +.\" 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 +.B 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. + +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 poll (2), +.BR ppoll (2), +.BR read (2), +.BR write (2), +and +.BR close (2). +.PP +.BR fanotify_init (2) +creates and initializes an fanotify notification group and returns a file +descriptor referring to it. +.PP +An fanotify notification group is an internal object of the kernel which 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. +One mask (the mark mask) defines file activities for which an event shall be +created. +Another mask (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 +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. +.PP +Two types of events exist: notification events and permission events. +Notification events are only 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. +.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. +.PP +.BR fanotify_mark (2) +adds a file, directory, or mount to the group and specifies which events +shall be reported (or ignored), or removes or modifies such an entry. +.PP +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). +.PP +All events for an fanotify group are collected in a queue. +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. +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. +.PP +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 + +.TP 15 +.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 principal 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 structures. +It must be compared to +.B FANOTIFY_METADATA_VERSION +to verify that the structures at runtime match the structures 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. +It has internal the flag +.B FMODE_NONOTIFY +set. +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. +More than one of the following flags can be set at once in the bit mask. +.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 that was only opened for reading +.RB ( O_RDONLY ) +or a directory 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 +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE). +.PP +The following macros are provided to iterate over a buffer containing fanotify +event metadata returned by +.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 +.IT len . +.PP +For permission events, the application must +.BR write (2) +a structure of the following form to the +.B fanotify +file descriptor: + +.in +4n +.nf +struct fanotify_response { + __s32 fd; + __u32 response; +}; +.fi +.in + +.TP 15 +.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 has been denied, the requesting application call will receive an +error +.BR EPERM . +.PP +To end listening, it is sufficient to +.BR close (2) +the fanotify file descriptor. +The outstanding permission events will be set to allowed, and all resources +will be returned to the kernel. +.PP +The file +.I /proc/<pid>/fdinfo/<fd> +contains information about fanotify marks for file descriptor +.I fd +of process +.IR pid . +See +.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 +A write enabled file descriptor shall be created for a file that is executing. +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 the event occured for a monitored file that is currently being execuded. +.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 bugs existed: +.IP * 3 +.\" FIXME: Patch is in linux-next-20140424. +.BR readdir (2) +does not create a +.B FAN_ACCESS +event. +.IP * +.\" 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 in +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 passed as 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 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 for O_LARGEFILE +#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' */ + +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); + } + + /* Check that the event contains a file descriptor. */ + + 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: "); + } + + /* Determine path of the file accessed. */ + + 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", path); + + /* Close the file descriptor of the event. */ + + close(metadata\->fd); + printf("\\n"); + } + + /* Forward pointer 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) { + printf("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"); + close(fd); + 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) + continue; + perror("poll"); + 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); + } + } + } + + /* Close fanotify file descriptor. */ + + close(fd); + printf("Listening for events stopped.\\n"); + return EXIT_SUCCESS; +} +.fi +.SH "SEE ALSO" +.ad l +.BR fanotify_init (2), +.BR fanotify_mark (2), +.BR inotify (7) diff --git a/man7/inotify.7 b/man7/inotify.7 index 17462c6..da76b2a 100644 --- a/man7/inotify.7 +++ b/man7/inotify.7 @@ -760,7 +760,8 @@ unread event. .BR inotify_init1 (2), .BR inotify_rm_watch (2), .BR read (2), -.BR stat (2) +.BR stat (2), +.BR fanotify (7) .IR Documentation/filesystems/inotify.txt in the Linux kernel source tree -- 1.9.2 -- 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