inotify

提供: セキュリティ
移動: 案内検索
スポンサーリンク

inotify とは、Linuxファイルシステム のイベントを監視するための仕組みです。FreeBSD における kevent/kqueue といえます。

読み方

inotify
あいのーてぃふぁい

概要

inotify は、Linux において ファイル改竄検知(セキュリティ監視)に役立つ仕組みです。inotify-toolsを利用することで、リアルタイム監視を簡単に実現できます。

inotify は、ファイルシステム を監視するためのシステムコールを提供します。inotify-tools は、inotifyの機能を利用するためのプログラムを提供します。

inotify は、Linuxカーネル 2.6.13 で、組み込まれました。  ファイルシステムのイベント監視は、ファイルマネージャーやセキュリティのツールなどに必要不可欠です。inotify は、1つのファイル記述子を開くことで、1つ以上のファイルやディレクトリのオープン、クローズ、移動・名前の変更、削除、作成、属性の変更などのイベントを指定して監視できます。 イベント監視に select や poll を使用できます。 inotify は、再帰的に監視できません。サブディレクトリの監視には、サブディレクトリを inotify_add_watch() で追加する必要があります。

inotify 以前のdnotify では、ディレクトリごとにファイル記述子を開く必要があり、複数の監視対象が存在する場合、コストが大きく、シグナルハンドリングの扱いにくさも問題でした。また、dnotify では、変更を調べるために stat の情報を持ち続けて、比較しなければなりませんでした。

インストール

inotify の API を C言語から利用する場合には、インストールするものはありません。 inotify-toolsは、インストールが必要です。inotify-toolsを参照してください。

サンプルコード inotify.c

このプログラムは、一度だけ、イベントを拾って、終了します。 一回の read で取得できるイベントだけを取得します。 バッファサイズの上限を超える場合は、うまくハンドリングできないでしょう。

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
 
#include <sys/inotify.h>
#include <linux/limits.h>
 
#define INOTIFY_BUFFER_SIZE     ((sizeof(struct inotify_event) + NAME_MAX + 1) * 4096)
 
int
Inotify_init (void) {
        int fd = inotify_init ();
        if (fd < 0) {
                perror ("inotify_init");
                return (fd);
        }
        return (fd);
}
 
int
Inotify_add_watch (int fd, const char *pathname, uint32_t mask) {
        int     watch_fd = inotify_add_watch (fd, pathname, mask);
        if (watch_fd == -1) {
                warn ("can not add inotify:fd=%d, path=%s, mask=%u",
				fd, pathname, mask);
        }
        return (watch_fd);
}
 
int
read_events (int fd) {
        int     r = -1;
        char    buffer [INOTIFY_BUFFER_SIZE] = { 0 };
        struct inotify_event    *event_ptr = NULL;
 
        r = read (fd, buffer, INOTIFY_BUFFER_SIZE);
        if (r <= 0) {
                return (r);
        }
 
        int offset = 0;
 
        while (offset < r) {
                event_ptr = (struct inotify_event *) & buffer [offset];
 
                (void) printf ("name=%s\n", event_ptr->name);
 
                offset += sizeof (struct inotify_event) + event_ptr->len;
        }
 
        return r;
}
 
int
main (int argc, char *argv[])
{
        int     inotify_fd = Inotify_init();
        if (inotify_fd < 0) {
                errx (EXIT_FAILURE, "can not init inotify");
        }
        long    mask    = IN_ALL_EVENTS;
        char    *path1  = "/tmp";
 
        int     wd1 = Inotify_add_watch (inotify_fd, path1, mask);
 
        read_events (inotify_fd);
 
        exit (EXIT_SUCCESS);
}

使い方

$ cc inotify.c

a.out を実行し、 /tmp のファイルを適当にいじります。

$ ./a.out

/tmp/b に追記してみました。

$ echo hoge >> /tmp/b

/tmp/b に追記したとき、3つのイベントが取得されました。

$ ./a.out
name=b
name=b
name=b

カーネルパラメーター

inotify に関連するカーネルのパラメーターがあります。

$ ls /proc/sys/fs/inotify/
max_queued_events  max_user_instances  max_user_watches

関連項目




スポンサーリンク