NAME
Linux::Fanotify - Perl interface to the Linux fanotify API
VERSION
Version 1.1
SYNOPSIS
use Linux::Fanotify qw(:consts);
use Fcntl; # Provides O_* constants required for fanotify_init
my $fanogrp = new Linux::Fanotify::FanotifyGroup(
FAN_CLOEXEC | FAN_CLASS_CONTENT,
O_RDONLY | O_LARGEFILE
) || die("Could not initialize fanotify: $!");
$fanogrp->mark(
FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_OPEN_PERM | FAN_CLOSE_WRITE, -1, $path
) || die("Could not mark $path: $!\n");
while (1) {
my @events = $fanogrp->read();
foreach my $e (@events) {
if ($e->needsResponse()) {
print("Allowing a request:\n$e\n");
$e->allow();
}
}
}
DESCRIPTION
The fanotify API is a filesystem monitoring interface in the Linux kernel. It is intended to be used by file scanners such as virus and malware scanners or file indexers.
fanotify has been part of the Linux kernel since 2.6.37 (but needs to be enabled in the kernel configuration).
This perl module provides a Perl binding for that API. The low level functions fanotify_init and fanotify_mark are available similarly to the original C functions, but provide a more abstract interface for easier usage in perl programs.
Linux::Fanotify provides a functional as well as an object oriented interface. The latter is the recommended way of interacting with the module.
fanotify basics
The fanotify kernel API provides two basic functions, plus a file (descriptor) based interface from which events can be read, and which is used to respond to such events.
The fanotify_init()
call is used to "connect" the kernel, which responds with creating a notification group (also: fanotify event group, ...). Notification groups can then be used to fanotify_mark()
file system objects, most prominently mount points, directories, or files. During marking, the type of requested events can be determined. This can be either a simple notification about operations, or a request for permission.
After marking such objects, a program can read from the notification group file descriptor to receive events; in case of permission requests, a response needs to be written to the notification group.
As of today (mid 2014), the fanotify man pages have not yet made their way into the distributions, so please consult the Linux man pages project instead. The relevant pages are fanotify(7), fanotify_init(2), and fanotify_mark(2). Please note that man pages prior to version 3.68, released 2014-05-28, are incorrect.
About this module
This module's interface closely resembles the low level functionality. The fanotify functions can directly be accessed (although the OO interface is recommended).
The return values of the offered functions and methods are perl style (in case of error, 0 or undef is returned) rather than C style (where 0 is returned in case of success).
Calling fanotify_init requires the CAP_SYS_ADMIN capability ("you need root", except that you don't).
Object oriented interface
Package Linux::Fanotify
Package-global variable $Linux::Fanotify::default_response
This package-global variable triggers a default response for permission events in case no explicit response has been issued.
The variable can contain a value of FAN_ALLOW
, FAN_DENY
, -1
, 0
, or any other integer. Its default is -1
.
Due to its system related nature, the fanotify API is good for all kinds of mess. When events are "lost" without properly responding to them, consecutive events can no longer properly answered (responses will allow/deny older events, rather than the ones they were intended to). I cannot imagine any case where one would want to trigger such a behavior intentionally, so its best to leave this variable untouched, and Linux::Fanotify
will take care of not leaking any file descriptors, and answering them with a sensible default just in case.
However, if you intend to shoot yourself in the foot, you can set this variable to 0. This will result in not automatically responding to events being manually closed or going out of scope.
The default -1
results in Linux::Fanotify
choosing its own default, currently FAN_DENY
.
Class method init($flags, $event_f_flags)
Identical to the Linux::Fanotify::FanotifyGroup constructor. See the documentation below.
Package Linux::Fanotify::FanotifyGroup
Package-global variable $Linux::Fanotify::FanotifyGroup::autoclose
This variable defaults to 1 and results in the fanotify group being closed when objects of this type are destroyed (e.g. by going out of scope).
This almost definitely is what you want. However, if you use multithreading or similar wizardry, passing around objects may result in destruction of copies of this object and subsequent, wrongly closing of the notification group.
Take care when setting this to 0 (or undef).
Constructor new($flags, $event_f_flags)
Constructs and returns a new Linux::Fanotify::FanotifyGroup
object.
Please consult the aforementioned man pages for information on $flags
and $event_f_flags
.
Returns undef
in case of error; consult "$!" in perlvar in this case.
Object method mark($flags, $mask, $dirfd, $pathname)
Marks the given entity ($dirfd, $pathname) in the current notification group with the given properties.
Again, see the man pages for detailed information about the arguments.
$flags
can be one of FAN_MARK_ADD
, FAN_MARK_REMOVE
, and FAN_MARK_FLUSH
to describe the respective operation
$mask
describes the operations for which the program listens.
$dirfd
and $pathname
describe the file system object to watch. Please note that $dirfd
needs to be a numeric file descriptor (such as returned by sysopen and friends), in contrast to a perl file handle. The "fileno" in perlfunc function can be used to get a file descriptor for a perl file handle.
Returns true in case of success, undef otherwise (see "$!" in perlvar in that case).
Object method read([$count])
This function returns a list of ""Package Linux::Fanotify::Event
" objects. The optional $count
argument may limit the number of returned events. As the kernel uses an event queue, programs may read a list of events instead of sequentally reading single events for performance reasons.
See the ""Package Linux::Fanotify::Event
" description below for more information about the returned objects.
The $count
argument is optional, and defaults to a value that results in an average-sized internal buffer. Using a value of 1 is supported. This perl module limits the maximum value of $count
to 4096.
Unless the FAN_NONBLOCK
flag has been set while initializing the fanotify group, the read call blocks and never returns an empty list.
For non blocking reads, the empty list is returned, and errno is EAGAIN. Other cases are directly passed on from the low level calls.
Object method getfd()
Returns the file descriptor of the notification group.
Allows for all kinds of messing around; be careful. May be useful for poll() or select() calls on the returned file descriptor.
After a manual closing of a notification group, this will be -1.
Object method close()
Closes the notification group.
This method does not have to be called manually (unless "Package-global variable $Linux::Fanotify::FanotifyGroup::autoclose
" has been set to 0); the object's destruction will automatically close the file descriptor.
Any events present in the event queue will be flushed (that includes an implicit "allow" of queued permission events).
Returns true in case of success, undef in case of error.
Package Linux::Fanotify::Event
Linux::Fanotify::Event
objects reflect event queue entries as returned by the system. Please note that event objects use an internal representation of the event meta data and can only be accessed via the described methods.
Use the getter methods listed below to get information about the event properties.
Package-global variable $Linux::Fanotify::Event::autoclose
This variable defaults to 1 and results in the event's file descriptor being closed when objects of this type are destroyed (e.g. by going out of scope).
This almost definitely is what you want. However, if you use multithreading or similar witchcraft, passing around objects may result in destruction of copies of this object and subsequent, wrongly closing of the files.
Take care when setting this to 0 (or undef) and manually close every event's file descriptor.
Object method close()
Closes the event's file descriptor. For non-permission events, this results in releasing the respective kernel data structures (only a limited amount of files can be kept open per process).
For permission events (FAN_OPEN_PERM
, FAN_ACCESS_PERM
), a default response is created in case no explicit response was issued. See above for more information about default responses.
Manually closing the file descriptor is normally not required (unless the "Package-global variable $Linux::Fanotify::Event::autoclose
" has been set to a false value); as soon as the event object is going out of scope, it will automatically be closed to prevent leaking file descriptors. If you intentionally want to keep a file descriptor open, store the event object in a variable of your choice.
Returns true in case of success, undef in case of error.
Object method needsResponse
Returns whether the event object (still) requires a response, i.e., it was (a) a FAN_OPEN_PERM or FAN_ACCESS_PERM in the first place, and (b) was not already responed.
Object method allow()
Respond to the event with a "FAN_ALLOW", allowing the operation.
Object method deny()
Respond to the event with a "FAN_DENY", denying the operation.
Getter methods
The following getter methods provide read only access to the properties of an event:
event_len
vers
metadata_len
mask
fd
pid
All getters directly return the original data structure's property unaltered. At the time of writing, event_len
and metadata_len
contain the length of an event meta data structure, 24 bytes.
To get the file name for the requested file descriptor, one can use a readlink()
call on the process' proc entry:
readlink("/proc/self/fd/" . $event->fd);
Functional interface
Using the object oriented interface described above is recommended in all cases. Not all object methods (especially the event object getters) have functional counterparts. However, the low level functions can be accessed with normal function calls.
Function fanotify_init($flags, $event_f_flags)
Initializes and returns a fanotify group.
In case of an error, returns undef.
Function fanotify_mark($notgrp, $flags, $mask, $dirfd, $pathname)
Marks a file system object to be monitored via the given notgrp.
See the respective object method for information on the arguments.
Function fanotify_read($notgrp [, $max)
Read events from the queue described by $notgrp
. Limited to $max
if given, limited to a module default otherwise.
Function fanotify_write($event, $response
Respond to an event with FAN_ALLOW or FAN_DENY. No other responses are currently accepted.
Returns the number of bytes written to the fanotify group file descriptor on success (you can expect this to be true), undef otherwise.
EXPORTED SYMBOLS
Per default, no symbols are exported by this module. However, the constants as well as the functions of the "Functional interface" are exportable.
By using the export tags :consts
and :funcs
, all of the respective symbols are importable. Use
use Linux::Fanotify qw(:consts);
to import all constants.
The fanotify_init calls (new
constructor, init
class method, fanotify_init
function) use O_* constants that are exported by the Fcntl module. In most cases, you want to use
that module as well.
AUTHOR
Bastian Friedrich <bastian@cpan.org> or <bastian@friedrich.link>
COPYRIGHT and LICENSE
Copyright (C) 2014 Bastian Friedrich. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.