Blame man7/fanotify.7

Packit 7cfc04
.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de>
Packit 7cfc04
.\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com>
Packit 7cfc04
.\"
Packit 7cfc04
.\" %%%LICENSE_START(VERBATIM)
Packit 7cfc04
.\" Permission is granted to make and distribute verbatim copies of this
Packit 7cfc04
.\" manual provided the copyright notice and this permission notice are
Packit 7cfc04
.\" preserved on all copies.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Permission is granted to copy and distribute modified versions of
Packit 7cfc04
.\" this manual under the conditions for verbatim copying, provided that
Packit 7cfc04
.\" the entire resulting derived work is distributed under the terms of
Packit 7cfc04
.\" a permission notice identical to this one.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Since the Linux kernel and libraries are constantly changing, this
Packit 7cfc04
.\" manual page may be incorrect or out-of-date.  The author(s) assume.
Packit 7cfc04
.\" no responsibility for errors or omissions, or for damages resulting.
Packit 7cfc04
.\" from the use of the information contained herein.  The author(s) may.
Packit 7cfc04
.\" not have taken the same level of care in the production of this.
Packit 7cfc04
.\" manual, which is licensed free of charge, as they might when working.
Packit 7cfc04
.\" professionally.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Formatted or processed versions of this manual, if unaccompanied by
Packit 7cfc04
.\" the source, must acknowledge the copyright and authors of this work.
Packit 7cfc04
.\" %%%LICENSE_END
Packit 7cfc04
.TH FANOTIFY 7 2017-09-15 "Linux" "Linux Programmer's Manual"
Packit 7cfc04
.SH NAME
Packit 7cfc04
fanotify \- monitoring filesystem events
Packit 7cfc04
.SH DESCRIPTION
Packit 7cfc04
The fanotify API provides notification and interception of
Packit 7cfc04
filesystem events.
Packit 7cfc04
Use cases include virus scanning and hierarchical storage management.
Packit 7cfc04
Currently, only a limited set of events is supported.
Packit 7cfc04
In particular, there is no support for create, delete, and move events.
Packit 7cfc04
(See
Packit 7cfc04
.BR inotify (7)
Packit 7cfc04
for details of an API that does notify those events.)
Packit 7cfc04
.PP
Packit 7cfc04
Additional capabilities compared to the
Packit 7cfc04
.BR inotify (7)
Packit 7cfc04
API include the ability to monitor all of the objects
Packit 7cfc04
in a mounted filesystem,
Packit 7cfc04
the ability to make access permission decisions, and the
Packit 7cfc04
possibility to read or modify files before access by other applications.
Packit 7cfc04
.PP
Packit 7cfc04
The following system calls are used with this API:
Packit 7cfc04
.BR fanotify_init (2),
Packit 7cfc04
.BR fanotify_mark (2),
Packit 7cfc04
.BR read (2),
Packit 7cfc04
.BR write (2),
Packit 7cfc04
and
Packit 7cfc04
.BR close (2).
Packit 7cfc04
.SS fanotify_init(), fanotify_mark(), and notification groups
Packit 7cfc04
The
Packit 7cfc04
.BR fanotify_init (2)
Packit 7cfc04
system call creates and initializes an fanotify notification group
Packit 7cfc04
and returns a file descriptor referring to it.
Packit 7cfc04
.PP
Packit 7cfc04
An fanotify notification group is a kernel-internal object that holds
Packit 7cfc04
a list of files, directories, and mount points for which events shall be
Packit 7cfc04
created.
Packit 7cfc04
.PP
Packit 7cfc04
For each entry in an fanotify notification group, two bit masks exist: the
Packit 7cfc04
.I mark
Packit 7cfc04
mask and the
Packit 7cfc04
.I ignore
Packit 7cfc04
mask.
Packit 7cfc04
The mark mask defines file activities for which an event shall be created.
Packit 7cfc04
The ignore mask defines activities for which no event shall be generated.
Packit 7cfc04
Having these two types of masks permits a mount point or directory to be
Packit 7cfc04
marked for receiving events, while at the same time ignoring events for
Packit 7cfc04
specific objects under that mount point or directory.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR fanotify_mark (2)
Packit 7cfc04
system call adds a file, directory, or mount to a notification group
Packit 7cfc04
and specifies which events
Packit 7cfc04
shall be reported (or ignored), or removes or modifies such an entry.
Packit 7cfc04
.PP
Packit 7cfc04
A possible usage of the ignore mask is for a file cache.
Packit 7cfc04
Events of interest for a file cache are modification of a file and closing
Packit 7cfc04
of the same.
Packit 7cfc04
Hence, the cached directory or mount point is to be marked to receive these
Packit 7cfc04
events.
Packit 7cfc04
After receiving the first event informing that a file has been modified,
Packit 7cfc04
the corresponding cache entry will be invalidated.
Packit 7cfc04
No further modification events for this file are of interest until the file
Packit 7cfc04
is closed.
Packit 7cfc04
Hence, the modify event can be added to the ignore mask.
Packit 7cfc04
Upon receiving the close event, the modify event can be removed from the
Packit 7cfc04
ignore mask and the file cache entry can be updated.
Packit 7cfc04
.PP
Packit 7cfc04
The entries in the fanotify notification groups refer to files and
Packit 7cfc04
directories via their inode number and to mounts via their mount ID.
Packit 7cfc04
If files or directories are renamed or moved within the same mount,
Packit 7cfc04
the respective entries survive.
Packit 7cfc04
If files or directories are deleted or moved to another mount or if mounts are
Packit 7cfc04
unmounted, the corresponding entries are deleted.
Packit 7cfc04
.SS The event queue
Packit 7cfc04
As events occur on the filesystem objects monitored by a notification group,
Packit 7cfc04
the fanotify system generates events that are collected in a queue.
Packit 7cfc04
These events can then be read (using
Packit 7cfc04
.BR read (2)
Packit 7cfc04
or similar)
Packit 7cfc04
from the fanotify file descriptor
Packit 7cfc04
returned by
Packit 7cfc04
.BR fanotify_init (2).
Packit 7cfc04
.PP
Packit 7cfc04
Two types of events are generated:
Packit 7cfc04
.I notification
Packit 7cfc04
events and
Packit 7cfc04
.I permission
Packit 7cfc04
events.
Packit 7cfc04
Notification events are merely informative
Packit 7cfc04
and require no action to be taken by
Packit 7cfc04
the receiving application except for closing the file descriptor passed
Packit 7cfc04
in the event (see below).
Packit 7cfc04
Permission events are requests to the receiving application to decide
Packit 7cfc04
whether permission for a file access shall be granted.
Packit 7cfc04
For these events, the recipient must write a response which decides whether
Packit 7cfc04
access is granted or not.
Packit 7cfc04
.PP
Packit 7cfc04
An event is removed from the event queue of the fanotify group
Packit 7cfc04
when it has been read.
Packit 7cfc04
Permission events that have been read are kept in an internal list of the
Packit 7cfc04
fanotify group until either a permission decision has been taken by
Packit 7cfc04
writing to the fanotify file descriptor or the fanotify file descriptor
Packit 7cfc04
is closed.
Packit 7cfc04
.SS Reading fanotify events
Packit 7cfc04
Calling
Packit 7cfc04
.BR read (2)
Packit 7cfc04
for the file descriptor returned by
Packit 7cfc04
.BR fanotify_init (2)
Packit 7cfc04
blocks (if the flag
Packit 7cfc04
.B FAN_NONBLOCK
Packit 7cfc04
is not specified in the call to
Packit 7cfc04
.BR fanotify_init (2))
Packit 7cfc04
until either a file event occurs or the call is interrupted by a signal
Packit 7cfc04
(see
Packit 7cfc04
.BR signal (7)).
Packit 7cfc04
.PP
Packit 7cfc04
After a successful
Packit 7cfc04
.BR read (2),
Packit 7cfc04
the read buffer contains one or more of the following structures:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
struct fanotify_event_metadata {
Packit 7cfc04
    __u32 event_len;
Packit 7cfc04
    __u8 vers;
Packit 7cfc04
    __u8 reserved;
Packit 7cfc04
    __u16 metadata_len;
Packit 7cfc04
    __aligned_u64 mask;
Packit 7cfc04
    __s32 fd;
Packit 7cfc04
    __s32 pid;
Packit 7cfc04
};
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
For performance reasons, it is recommended to use a large
Packit 7cfc04
buffer size (for example, 4096 bytes),
Packit 7cfc04
so that multiple events can be retrieved by a single
Packit 7cfc04
.BR read (2).
Packit 7cfc04
.PP
Packit 7cfc04
The return value of
Packit 7cfc04
.BR read (2)
Packit 7cfc04
is the number of bytes placed in the buffer,
Packit 7cfc04
or \-1 in case of an error (but see BUGS).
Packit 7cfc04
.PP
Packit 7cfc04
The fields of the
Packit 7cfc04
.I fanotify_event_metadata
Packit 7cfc04
structure are as follows:
Packit 7cfc04
.TP
Packit 7cfc04
.I event_len
Packit 7cfc04
This is the length of the data for the current event and the offset
Packit 7cfc04
to the next event in the buffer.
Packit 7cfc04
In the current implementation, the value of
Packit 7cfc04
.I event_len
Packit 7cfc04
is always
Packit 7cfc04
.BR FAN_EVENT_METADATA_LEN .
Packit 7cfc04
However, the API is designed to allow
Packit 7cfc04
variable-length structures to be returned in the future.
Packit 7cfc04
.TP
Packit 7cfc04
.I vers
Packit 7cfc04
This field holds a version number for the structure.
Packit 7cfc04
It must be compared to
Packit 7cfc04
.B FANOTIFY_METADATA_VERSION
Packit 7cfc04
to verify that the structures returned at runtime match
Packit 7cfc04
the structures defined at compile time.
Packit 7cfc04
In case of a mismatch, the application should abandon trying to use the
Packit 7cfc04
fanotify file descriptor.
Packit 7cfc04
.TP
Packit 7cfc04
.I reserved
Packit 7cfc04
This field is not used.
Packit 7cfc04
.TP
Packit 7cfc04
.I metadata_len
Packit 7cfc04
This is the length of the structure.
Packit 7cfc04
The field was introduced to facilitate the implementation of
Packit 7cfc04
optional headers per event type.
Packit 7cfc04
No such optional headers exist in the current implementation.
Packit 7cfc04
.TP
Packit 7cfc04
.I mask
Packit 7cfc04
This is a bit mask describing the event (see below).
Packit 7cfc04
.TP
Packit 7cfc04
.I fd
Packit 7cfc04
This is an open file descriptor for the object being accessed, or
Packit 7cfc04
.B FAN_NOFD
Packit 7cfc04
if a queue overflow occurred.
Packit 7cfc04
The file descriptor can be used to access the contents
Packit 7cfc04
of the monitored file or directory.
Packit 7cfc04
The reading application is responsible for closing this file descriptor.
Packit 7cfc04
.IP
Packit 7cfc04
When calling
Packit 7cfc04
.BR fanotify_init (2),
Packit 7cfc04
the caller may specify (via the
Packit 7cfc04
.I event_f_flags
Packit 7cfc04
argument) various file status flags that are to be set
Packit 7cfc04
on the open file description that corresponds to this file descriptor.
Packit 7cfc04
In addition, the (kernel-internal)
Packit 7cfc04
.B FMODE_NONOTIFY
Packit 7cfc04
file status flag is set on the open file description.
Packit 7cfc04
This flag suppresses fanotify event generation.
Packit 7cfc04
Hence, when the receiver of the fanotify event accesses the notified file or
Packit 7cfc04
directory using this file descriptor, no additional events will be created.
Packit 7cfc04
.TP
Packit 7cfc04
.I pid
Packit 7cfc04
This is the ID of the process that caused the event.
Packit 7cfc04
A program listening to fanotify events can compare this PID
Packit 7cfc04
to the PID returned by
Packit 7cfc04
.BR getpid (2),
Packit 7cfc04
to determine whether the event is caused by the listener itself,
Packit 7cfc04
or is due to a file access by another process.
Packit 7cfc04
.PP
Packit 7cfc04
The bit mask in
Packit 7cfc04
.I mask
Packit 7cfc04
indicates which events have occurred for a single filesystem object.
Packit 7cfc04
Multiple bits may be set in this mask,
Packit 7cfc04
if more than one event occurred for the monitored filesystem object.
Packit 7cfc04
In particular,
Packit 7cfc04
consecutive events for the same filesystem object and originating from the
Packit 7cfc04
same process may be merged into a single event, with the exception that two
Packit 7cfc04
permission events are never merged into one queue entry.
Packit 7cfc04
.PP
Packit 7cfc04
The bits that may appear in
Packit 7cfc04
.I mask
Packit 7cfc04
are as follows:
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_ACCESS
Packit 7cfc04
A file or a directory (but see BUGS) was accessed (read).
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_OPEN
Packit 7cfc04
A file or a directory was opened.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_MODIFY
Packit 7cfc04
A file was modified.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_CLOSE_WRITE
Packit 7cfc04
A file that was opened for writing
Packit 7cfc04
.RB ( O_WRONLY
Packit 7cfc04
or
Packit 7cfc04
.BR O_RDWR )
Packit 7cfc04
was closed.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_CLOSE_NOWRITE
Packit 7cfc04
A file or directory that was opened read-only
Packit 7cfc04
.RB ( O_RDONLY )
Packit 7cfc04
was closed.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_Q_OVERFLOW
Packit 7cfc04
The event queue exceeded the limit of 16384 entries.
Packit 7cfc04
This limit can be overridden by specifying the
Packit 7cfc04
.BR FAN_UNLIMITED_QUEUE
Packit 7cfc04
flag when calling
Packit 7cfc04
.BR fanotify_init (2).
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_ACCESS_PERM
Packit 7cfc04
An application wants to read a file or directory, for example using
Packit 7cfc04
.BR read (2)
Packit 7cfc04
or
Packit 7cfc04
.BR readdir (2).
Packit 7cfc04
The reader must write a response (as described below)
Packit 7cfc04
that determines whether the permission to
Packit 7cfc04
access the filesystem object shall be granted.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_OPEN_PERM
Packit 7cfc04
An application wants to open a file or directory.
Packit 7cfc04
The reader must write a response that determines whether the permission to
Packit 7cfc04
open the filesystem object shall be granted.
Packit 7cfc04
.PP
Packit 7cfc04
To check for any close event, the following bit mask may be used:
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_CLOSE
Packit 7cfc04
A file was closed.
Packit 7cfc04
This is a synonym for:
Packit 7cfc04
.IP
Packit 7cfc04
    FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
Packit 7cfc04
.PP
Packit 7cfc04
The following macros are provided to iterate over a buffer containing
Packit 7cfc04
fanotify event metadata returned by a
Packit 7cfc04
.BR read (2)
Packit 7cfc04
from an fanotify file descriptor:
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_EVENT_OK(meta, len)
Packit 7cfc04
This macro checks the remaining length
Packit 7cfc04
.I len
Packit 7cfc04
of the buffer
Packit 7cfc04
.I meta
Packit 7cfc04
against the length of the metadata structure and the
Packit 7cfc04
.I event_len
Packit 7cfc04
field of the first metadata structure in the buffer.
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_EVENT_NEXT(meta, len)
Packit 7cfc04
This macro uses the length indicated in the
Packit 7cfc04
.I event_len
Packit 7cfc04
field of the metadata structure pointed to by
Packit 7cfc04
.IR meta
Packit 7cfc04
to calculate the address of the next metadata structure that follows
Packit 7cfc04
.IR meta .
Packit 7cfc04
.I len
Packit 7cfc04
is the number of bytes of metadata that currently remain in the buffer.
Packit 7cfc04
The macro returns a pointer to the next metadata structure that follows
Packit 7cfc04
.IR meta ,
Packit 7cfc04
and reduces
Packit 7cfc04
.I len
Packit 7cfc04
by the number of bytes in the metadata structure that
Packit 7cfc04
has been skipped over (i.e., it subtracts
Packit 7cfc04
.IR meta\->event_len
Packit 7cfc04
from
Packit 7cfc04
.IR len ).
Packit 7cfc04
.PP
Packit 7cfc04
In addition, there is:
Packit 7cfc04
.TP
Packit 7cfc04
.B FAN_EVENT_METADATA_LEN
Packit 7cfc04
This macro returns the size (in bytes) of the structure
Packit 7cfc04
.IR fanotify_event_metadata .
Packit 7cfc04
This is the minimum size (and currently the only size) of any event metadata.
Packit 7cfc04
.\"
Packit 7cfc04
.SS Monitoring an fanotify file descriptor for events
Packit 7cfc04
When an fanotify event occurs, the fanotify file descriptor indicates as
Packit 7cfc04
readable when passed to
Packit 7cfc04
.BR epoll (7),
Packit 7cfc04
.BR poll (2),
Packit 7cfc04
or
Packit 7cfc04
.BR select (2).
Packit 7cfc04
.SS Dealing with permission events
Packit 7cfc04
For permission events, the application must
Packit 7cfc04
.BR write (2)
Packit 7cfc04
a structure of the following form to the
Packit 7cfc04
fanotify file descriptor:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
struct fanotify_response {
Packit 7cfc04
    __s32 fd;
Packit 7cfc04
    __u32 response;
Packit 7cfc04
};
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
The fields of this structure are as follows:
Packit 7cfc04
.TP
Packit 7cfc04
.I fd
Packit 7cfc04
This is the file descriptor from the structure
Packit 7cfc04
.IR fanotify_event_metadata .
Packit 7cfc04
.TP
Packit 7cfc04
.I response
Packit 7cfc04
This field indicates whether or not the permission is to be granted.
Packit 7cfc04
Its value must be either
Packit 7cfc04
.B FAN_ALLOW
Packit 7cfc04
to allow the file operation or
Packit 7cfc04
.B FAN_DENY
Packit 7cfc04
to deny the file operation.
Packit 7cfc04
.PP
Packit 7cfc04
If access is denied, the requesting application call will receive an
Packit 7cfc04
.BR EPERM
Packit 7cfc04
error.
Packit 7cfc04
.SS Closing the fanotify file descriptor
Packit 7cfc04
.PP
Packit 7cfc04
When all file descriptors referring to the fanotify notification group are
Packit 7cfc04
closed, the fanotify group is released and its resources
Packit 7cfc04
are freed for reuse by the kernel.
Packit 7cfc04
Upon
Packit 7cfc04
.BR close (2),
Packit 7cfc04
outstanding permission events will be set to allowed.
Packit 7cfc04
.SS /proc/[pid]/fdinfo
Packit 7cfc04
The file
Packit 7cfc04
.I /proc/[pid]/fdinfo/[fd]
Packit 7cfc04
contains information about fanotify marks for file descriptor
Packit 7cfc04
.I fd
Packit 7cfc04
of process
Packit 7cfc04
.IR pid .
Packit 7cfc04
See
Packit 7cfc04
.BR proc (5)
Packit 7cfc04
for details.
Packit 7cfc04
.SH ERRORS
Packit 7cfc04
In addition to the usual errors for
Packit 7cfc04
.BR read (2),
Packit 7cfc04
the following errors can occur when reading from the
Packit 7cfc04
fanotify file descriptor:
Packit 7cfc04
.TP
Packit 7cfc04
.B EINVAL
Packit 7cfc04
The buffer is too small to hold the event.
Packit 7cfc04
.TP
Packit 7cfc04
.B EMFILE
Packit 7cfc04
The per-process limit on the number of open files has been reached.
Packit 7cfc04
See the description of
Packit 7cfc04
.B RLIMIT_NOFILE
Packit 7cfc04
in
Packit 7cfc04
.BR getrlimit (2).
Packit 7cfc04
.TP
Packit 7cfc04
.B ENFILE
Packit 7cfc04
The system-wide limit on the total number of open files has been reached.
Packit 7cfc04
See
Packit 7cfc04
.I /proc/sys/fs/file-max
Packit 7cfc04
in
Packit 7cfc04
.BR proc (5).
Packit 7cfc04
.TP
Packit 7cfc04
.B ETXTBSY
Packit 7cfc04
This error is returned by
Packit 7cfc04
.BR read (2)
Packit 7cfc04
if
Packit 7cfc04
.B O_RDWR
Packit 7cfc04
or
Packit 7cfc04
.B O_WRONLY
Packit 7cfc04
was specified in the
Packit 7cfc04
.I event_f_flags
Packit 7cfc04
argument when calling
Packit 7cfc04
.BR fanotify_init (2)
Packit 7cfc04
and an event occurred for a monitored file that is currently being executed.
Packit 7cfc04
.PP
Packit 7cfc04
In addition to the usual errors for
Packit 7cfc04
.BR write (2),
Packit 7cfc04
the following errors can occur when writing to the fanotify file descriptor:
Packit 7cfc04
.TP
Packit 7cfc04
.B EINVAL
Packit 7cfc04
Fanotify access permissions are not enabled in the kernel configuration
Packit 7cfc04
or the value of
Packit 7cfc04
.I response
Packit 7cfc04
in the response structure is not valid.
Packit 7cfc04
.TP
Packit 7cfc04
.B ENOENT
Packit 7cfc04
The file descriptor
Packit 7cfc04
.I fd
Packit 7cfc04
in the response structure is not valid.
Packit 7cfc04
This may occur when a response for the permission event has already been
Packit 7cfc04
written.
Packit 7cfc04
.SH VERSIONS
Packit 7cfc04
The fanotify API was introduced in version 2.6.36 of the Linux kernel and
Packit 7cfc04
enabled in version 2.6.37.
Packit 7cfc04
Fdinfo support was added in version 3.8.
Packit 7cfc04
.SH CONFORMING TO
Packit 7cfc04
The fanotify API is Linux-specific.
Packit 7cfc04
.SH NOTES
Packit 7cfc04
The fanotify API is available only if the kernel was built with the
Packit 7cfc04
.B CONFIG_FANOTIFY
Packit 7cfc04
configuration option enabled.
Packit 7cfc04
In addition, fanotify permission handling is available only if the
Packit 7cfc04
.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
Packit 7cfc04
configuration option is enabled.
Packit 7cfc04
.SS Limitations and caveats
Packit 7cfc04
Fanotify reports only events that a user-space program triggers through the
Packit 7cfc04
filesystem API.
Packit 7cfc04
As a result,
Packit 7cfc04
it does not catch remote events that occur on network filesystems.
Packit 7cfc04
.PP
Packit 7cfc04
The fanotify API does not report file accesses and modifications that
Packit 7cfc04
may occur because of
Packit 7cfc04
.BR mmap (2),
Packit 7cfc04
.BR msync (2),
Packit 7cfc04
and
Packit 7cfc04
.BR munmap (2).
Packit 7cfc04
.PP
Packit 7cfc04
Events for directories are created only if the directory itself is opened,
Packit 7cfc04
read, and closed.
Packit 7cfc04
Adding, removing, or changing children of a marked directory does not create
Packit 7cfc04
events for the monitored directory itself.
Packit 7cfc04
.PP
Packit 7cfc04
Fanotify monitoring of directories is not recursive:
Packit 7cfc04
to monitor subdirectories under a directory,
Packit 7cfc04
additional marks must be created.
Packit 7cfc04
(But note that the fanotify API provides no way of detecting when a
Packit 7cfc04
subdirectory has been created under a marked directory,
Packit 7cfc04
which makes recursive monitoring difficult.)
Packit 7cfc04
Monitoring mounts offers the capability to monitor a whole directory tree.
Packit 7cfc04
.PP
Packit 7cfc04
The event queue can overflow.
Packit 7cfc04
In this case, events are lost.
Packit 7cfc04
.SH BUGS
Packit 7cfc04
Before Linux 3.19,
Packit 7cfc04
.BR fallocate (2)
Packit 7cfc04
did not generate fanotify events.
Packit 7cfc04
Since Linux 3.19,
Packit 7cfc04
.\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35
Packit 7cfc04
calls to
Packit 7cfc04
.BR fallocate (2)
Packit 7cfc04
generate
Packit 7cfc04
.B FAN_MODIFY
Packit 7cfc04
events.
Packit 7cfc04
.PP
Packit 7cfc04
As of Linux 3.17,
Packit 7cfc04
the following bugs exist:
Packit 7cfc04
.IP * 3
Packit 7cfc04
On Linux, a filesystem object may be accessible through multiple paths,
Packit 7cfc04
for example, a part of a filesystem may be remounted using the
Packit 7cfc04
.IR \-\-bind
Packit 7cfc04
option of
Packit 7cfc04
.BR mount (8).
Packit 7cfc04
A listener that marked a mount will be notified only of events that were
Packit 7cfc04
triggered for a filesystem object using the same mount.
Packit 7cfc04
Any other event will pass unnoticed.
Packit 7cfc04
.IP *
Packit 7cfc04
.\" FIXME . A patch was proposed.
Packit 7cfc04
When an event is generated,
Packit 7cfc04
no check is made to see whether the user ID of the
Packit 7cfc04
receiving process has authorization to read or write the file
Packit 7cfc04
before passing a file descriptor for that file.
Packit 7cfc04
This poses a security risk, when the
Packit 7cfc04
.B CAP_SYS_ADMIN
Packit 7cfc04
capability is set for programs executed by unprivileged users.
Packit 7cfc04
.IP *
Packit 7cfc04
If a call to
Packit 7cfc04
.BR read (2)
Packit 7cfc04
processes multiple events from the fanotify queue and an error occurs,
Packit 7cfc04
the return value will be the total length of the events successfully
Packit 7cfc04
copied to the user-space buffer before the error occurred.
Packit 7cfc04
The return value will not be \-1, and
Packit 7cfc04
.I errno
Packit 7cfc04
will not be set.
Packit 7cfc04
Thus, the reading application has no way to detect the error.
Packit 7cfc04
.SH EXAMPLE
Packit 7cfc04
The following program demonstrates the usage of the fanotify API.
Packit 7cfc04
It marks the mount point passed as a command-line argument
Packit 7cfc04
and waits for events of type
Packit 7cfc04
.B FAN_PERM_OPEN
Packit 7cfc04
and
Packit 7cfc04
.BR FAN_CLOSE_WRITE .
Packit 7cfc04
When a permission event occurs, a
Packit 7cfc04
.B FAN_ALLOW
Packit 7cfc04
response is given.
Packit 7cfc04
.PP
Packit 7cfc04
The following output was recorded while editing the file
Packit 7cfc04
.IR /home/user/temp/notes .
Packit 7cfc04
Before the file was opened, a
Packit 7cfc04
.B FAN_OPEN_PERM
Packit 7cfc04
event occurred.
Packit 7cfc04
After the file was closed, a
Packit 7cfc04
.B FAN_CLOSE_WRITE
Packit 7cfc04
event occurred.
Packit 7cfc04
Execution of the program ends when the user presses the ENTER key.
Packit 7cfc04
.SS Example output
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
# ./fanotify_example /home
Packit 7cfc04
Press enter key to terminate.
Packit 7cfc04
Listening for events.
Packit 7cfc04
FAN_OPEN_PERM: File /home/user/temp/notes
Packit 7cfc04
FAN_CLOSE_WRITE: File /home/user/temp/notes
Packit 7cfc04
Packit 7cfc04
Listening for events stopped.
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.SS Program source
Packit 7cfc04
\&
Packit 7cfc04
.EX
Packit 7cfc04
#define _GNU_SOURCE     /* Needed to get O_LARGEFILE definition */
Packit 7cfc04
#include <errno.h>
Packit 7cfc04
#include <fcntl.h>
Packit 7cfc04
#include <limits.h>
Packit 7cfc04
#include <poll.h>
Packit 7cfc04
#include <stdio.h>
Packit 7cfc04
#include <stdlib.h>
Packit 7cfc04
#include <sys/fanotify.h>
Packit 7cfc04
#include <unistd.h>
Packit 7cfc04
Packit 7cfc04
/* Read all available fanotify events from the file descriptor 'fd' */
Packit 7cfc04
Packit 7cfc04
static void
Packit 7cfc04
handle_events(int fd)
Packit 7cfc04
{
Packit 7cfc04
    const struct fanotify_event_metadata *metadata;
Packit 7cfc04
    struct fanotify_event_metadata buf[200];
Packit 7cfc04
    ssize_t len;
Packit 7cfc04
    char path[PATH_MAX];
Packit 7cfc04
    ssize_t path_len;
Packit 7cfc04
    char procfd_path[PATH_MAX];
Packit 7cfc04
    struct fanotify_response response;
Packit 7cfc04
Packit 7cfc04
    /* Loop while events can be read from fanotify file descriptor */
Packit 7cfc04
Packit 7cfc04
    for(;;) {
Packit 7cfc04
Packit 7cfc04
        /* Read some events */
Packit 7cfc04
Packit 7cfc04
        len = read(fd, (void *) &buf, sizeof(buf));
Packit 7cfc04
        if (len == \-1 && errno != EAGAIN) {
Packit 7cfc04
            perror("read");
Packit 7cfc04
            exit(EXIT_FAILURE);
Packit 7cfc04
        }
Packit 7cfc04
Packit 7cfc04
        /* Check if end of available data reached */
Packit 7cfc04
Packit 7cfc04
        if (len <= 0)
Packit 7cfc04
            break;
Packit 7cfc04
Packit 7cfc04
        /* Point to the first event in the buffer */
Packit 7cfc04
Packit 7cfc04
        metadata = buf;
Packit 7cfc04
Packit 7cfc04
        /* Loop over all events in the buffer */
Packit 7cfc04
Packit 7cfc04
        while (FAN_EVENT_OK(metadata, len)) {
Packit 7cfc04
Packit 7cfc04
            /* Check that run\-time and compile\-time structures match */
Packit 7cfc04
Packit 7cfc04
            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
Packit 7cfc04
                fprintf(stderr,
Packit 7cfc04
                        "Mismatch of fanotify metadata version.\\n");
Packit 7cfc04
                exit(EXIT_FAILURE);
Packit 7cfc04
            }
Packit 7cfc04
Packit 7cfc04
            /* metadata\->fd contains either FAN_NOFD, indicating a
Packit 7cfc04
               queue overflow, or a file descriptor (a nonnegative
Packit 7cfc04
               integer). Here, we simply ignore queue overflow. */
Packit 7cfc04
Packit 7cfc04
            if (metadata\->fd >= 0) {
Packit 7cfc04
Packit 7cfc04
                /* Handle open permission event */
Packit 7cfc04
Packit 7cfc04
                if (metadata\->mask & FAN_OPEN_PERM) {
Packit 7cfc04
                    printf("FAN_OPEN_PERM: ");
Packit 7cfc04
Packit 7cfc04
                    /* Allow file to be opened */
Packit 7cfc04
Packit 7cfc04
                    response.fd = metadata\->fd;
Packit 7cfc04
                    response.response = FAN_ALLOW;
Packit 7cfc04
                    write(fd, &response,
Packit 7cfc04
                          sizeof(struct fanotify_response));
Packit 7cfc04
                }
Packit 7cfc04
Packit 7cfc04
                /* Handle closing of writable file event */
Packit 7cfc04
Packit 7cfc04
                if (metadata\->mask & FAN_CLOSE_WRITE)
Packit 7cfc04
                    printf("FAN_CLOSE_WRITE: ");
Packit 7cfc04
Packit 7cfc04
                /* Retrieve and print pathname of the accessed file */
Packit 7cfc04
Packit 7cfc04
                snprintf(procfd_path, sizeof(procfd_path),
Packit 7cfc04
                         "/proc/self/fd/%d", metadata\->fd);
Packit 7cfc04
                path_len = readlink(procfd_path, path,
Packit 7cfc04
                                    sizeof(path) \- 1);
Packit 7cfc04
                if (path_len == \-1) {
Packit 7cfc04
                    perror("readlink");
Packit 7cfc04
                    exit(EXIT_FAILURE);
Packit 7cfc04
                }
Packit 7cfc04
Packit 7cfc04
                path[path_len] = '\\0';
Packit 7cfc04
                printf("File %s\\n", path);
Packit 7cfc04
Packit 7cfc04
                /* Close the file descriptor of the event */
Packit 7cfc04
Packit 7cfc04
                close(metadata\->fd);
Packit 7cfc04
            }
Packit 7cfc04
Packit 7cfc04
            /* Advance to next event */
Packit 7cfc04
Packit 7cfc04
            metadata = FAN_EVENT_NEXT(metadata, len);
Packit 7cfc04
        }
Packit 7cfc04
    }
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
int
Packit 7cfc04
main(int argc, char *argv[])
Packit 7cfc04
{
Packit 7cfc04
    char buf;
Packit 7cfc04
    int fd, poll_num;
Packit 7cfc04
    nfds_t nfds;
Packit 7cfc04
    struct pollfd fds[2];
Packit 7cfc04
Packit 7cfc04
    /* Check mount point is supplied */
Packit 7cfc04
Packit 7cfc04
    if (argc != 2) {
Packit 7cfc04
        fprintf(stderr, "Usage: %s MOUNT\\n", argv[0]);
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    printf("Press enter key to terminate.\\n");
Packit 7cfc04
Packit 7cfc04
    /* Create the file descriptor for accessing the fanotify API */
Packit 7cfc04
Packit 7cfc04
    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
Packit 7cfc04
                       O_RDONLY | O_LARGEFILE);
Packit 7cfc04
    if (fd == \-1) {
Packit 7cfc04
        perror("fanotify_init");
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    /* Mark the mount for:
Packit 7cfc04
       \- permission events before opening files
Packit 7cfc04
       \- notification events after closing a write\-enabled
Packit 7cfc04
         file descriptor */
Packit 7cfc04
Packit 7cfc04
    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
Packit 7cfc04
                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
Packit 7cfc04
                      argv[1]) == \-1) {
Packit 7cfc04
        perror("fanotify_mark");
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    /* Prepare for polling */
Packit 7cfc04
Packit 7cfc04
    nfds = 2;
Packit 7cfc04
Packit 7cfc04
    /* Console input */
Packit 7cfc04
Packit 7cfc04
    fds[0].fd = STDIN_FILENO;
Packit 7cfc04
    fds[0].events = POLLIN;
Packit 7cfc04
Packit 7cfc04
    /* Fanotify input */
Packit 7cfc04
Packit 7cfc04
    fds[1].fd = fd;
Packit 7cfc04
    fds[1].events = POLLIN;
Packit 7cfc04
Packit 7cfc04
    /* This is the loop to wait for incoming events */
Packit 7cfc04
Packit 7cfc04
    printf("Listening for events.\\n");
Packit 7cfc04
Packit 7cfc04
    while (1) {
Packit 7cfc04
        poll_num = poll(fds, nfds, \-1);
Packit 7cfc04
        if (poll_num == \-1) {
Packit 7cfc04
            if (errno == EINTR)     /* Interrupted by a signal */
Packit 7cfc04
                continue;           /* Restart poll() */
Packit 7cfc04
Packit 7cfc04
            perror("poll");         /* Unexpected error */
Packit 7cfc04
            exit(EXIT_FAILURE);
Packit 7cfc04
        }
Packit 7cfc04
Packit 7cfc04
        if (poll_num > 0) {
Packit 7cfc04
            if (fds[0].revents & POLLIN) {
Packit 7cfc04
Packit 7cfc04
                /* Console input is available: empty stdin and quit */
Packit 7cfc04
Packit 7cfc04
                while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
Packit 7cfc04
                    continue;
Packit 7cfc04
                break;
Packit 7cfc04
            }
Packit 7cfc04
Packit 7cfc04
            if (fds[1].revents & POLLIN) {
Packit 7cfc04
Packit 7cfc04
                /* Fanotify events are available */
Packit 7cfc04
Packit 7cfc04
                handle_events(fd);
Packit 7cfc04
            }
Packit 7cfc04
        }
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    printf("Listening for events stopped.\\n");
Packit 7cfc04
    exit(EXIT_SUCCESS);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.SH SEE ALSO
Packit 7cfc04
.ad l
Packit 7cfc04
.BR fanotify_init (2),
Packit 7cfc04
.BR fanotify_mark (2),
Packit 7cfc04
.BR inotify (7)
Packit 7cfc04
.SH COLOPHON
Packit 7cfc04
This page is part of release 4.15 of the Linux
Packit 7cfc04
.I man-pages
Packit 7cfc04
project.
Packit 7cfc04
A description of the project,
Packit 7cfc04
information about reporting bugs,
Packit 7cfc04
and the latest version of this page,
Packit 7cfc04
can be found at
Packit 7cfc04
\%https://www.kernel.org/doc/man\-pages/.