Linux::Fanotify - Perl interface to the Linux fanotify API
Version 1.2.0
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(); } } }
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.
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.
fanotify_init()
fanotify_mark()
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.
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).
Linux::Fanotify
$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.
FAN_ALLOW
FAN_DENY
-1
0
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.
init($flags, $event_f_flags)
Identical to the Linux::Fanotify::FanotifyGroup constructor. See the documentation below.
Linux::Fanotify::FanotifyGroup
$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).
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.
$flags
$event_f_flags
Returns undef in case of error; consult "$!" in perlvar in this case.
undef
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
FAN_MARK_ADD
FAN_MARK_REMOVE
FAN_MARK_FLUSH
$mask describes the operations for which the program listens.
$mask
$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.
$dirfd
$pathname
Returns true in case of success, undef otherwise (see "$!" in perlvar in that case).
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.
Linux::Fanotify::Event
$count
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.
FAN_NONBLOCK
For non blocking reads, the empty list is returned, and errno is EAGAIN. Other cases are directly passed on from the low level calls.
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.
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.
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.
$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.
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.
FAN_OPEN_PERM
FAN_ACCESS_PERM
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.
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.
allow()
Respond to the event with a "FAN_ALLOW", allowing the operation.
deny()
Respond to the event with a "FAN_DENY", denying the operation.
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()
readlink("/proc/self/fd/" . $event->fd);
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.
fanotify_init($flags, $event_f_flags)
Initializes and returns a fanotify group.
In case of an error, returns undef.
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.
fanotify_read($notgrp [, $max)
Read events from the queue described by $notgrp. Limited to $max if given, limited to a module default otherwise.
$notgrp
$max
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.
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
:consts
:funcs
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.
new
init
fanotify_init
use
Bastian Friedrich <bastian@cpan.org> or <bastian@friedrich.link>
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.
To install Linux::Fanotify, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Linux::Fanotify
CPAN shell
perl -MCPAN -e shell install Linux::Fanotify
For more information on module installation, please visit the detailed CPAN module installation guide.