2014年3月25日火曜日

ClamAV のオンアクセス スキャン

ClamAV のオンアクセス スキャンを行おうとした場合、以前は ClamFS か Dazuko (Clamuko) を使用することになっていたが、最近のバージョンではカーネルの fanotify を使用した方法に変わっていた。これを (Gentoo で) 使ってみようとしたところ注意が必要な事項があったのでそれらについて記載する。
環境は以下のとおり。
  • linux-3.12.13 (amd64: これが重要!)
  • clamav-0.98.1 

    1. fanotify サポートの有効化

    1.1 カーネルオプション

    gentoo-sources ではデフォルト無効だった。
    File systems  --->
     [*] Filesystem wide access notification
    

    1.2 ClamAV

    Gentoo ebuild では 2014 年 3 月現在、clamav の fanotify サポートが無効化 (--disable-fanotify) されており、オンアクセス スキャンが使用できない。けれども、x86 / amd64 では fanotify サポートを無効化しなくとも動作させることができるので、当該オプションを削除して fanotify サポートを有効化させることが可能。

    2. サブディレクトリの検索

    オンアクセス スキャンの対象ディレクトリは clamd.conf の OnAccessIncludePath で指定することになるが、当該ディレクティブはサブディレクトリを対象としない。つまり、OnAccessIncludePath / と指定しても ~/eicar.com へのアクセスはスキャンされない。これは期待された動作らしい (!)。私が期待する動作は (サブディレクトリも含めて) ファイルシステム全体をスキャンすることだったため以下のようにコードを変更した。
    --- a/clamd/fan.c       2014-01-13 12:02:18.000000000 -0500
    +++ b/clamd/fan.c       2014-03-23 20:33:12.382967001 -0400
    @@ -134,7 +134,7 @@
     
         if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
            while(pt) {
    -           if(fanotify_mark(fan_fd, FAN_MARK_ADD, fan_mask, fan_fd, pt->strarg) != 0) {
    +           if(fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, fan_fd, pt->strarg) != 0) {
                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
                    return NULL;
                } else
    
    FAN_MARK_MOUNT はマウントポイント全体を対象にするオプションのためサブディレクトリの検索とは異なるが、まあファイルシステム全体を対象にしてスキャンする使い方には問題がない。

    3. ebuild とパッチ

    ClamAV か関連の上記 2 点に対応した ebuild とパッチ (x86 / amd64 用) を https://github.com/drmn/portage/tree/master/app-antivirus/clamav に置いた。

    参考

    履歴

    • 2014/03/26: カーネルオプションについて追記、FAN_MARK_MOUNT に関する説明の誤りを訂正 (K 氏ご指摘)

    2014年3月3日月曜日

    Portage の userpriv feature

    vmware-modules が以下のエラーで emerge できず、しばらく VMware Player を使えていなかった。
    # emerge -av1 vmware-modules
    
    These are the packages that would be merged, in order:
    
    Calculating dependencies... done!
    [ebuild   R   ~] app-emulation/vmware-modules-279.0  USE="-pax_kernel" 0 kB
    
    -- snip --
    
    >>> Compiling source in /var/tmp/portage/app-emulation/vmware-modules-279.0/work ...
     * Preparing vmblock module
    make -j -l 3 HOSTCC=x86_64-pc-linux-gnu-gcc CROSS_COMPILE=x86_64-pc-linux-gnu- 'LDFLAGS=-m elf_x86_64' auto-build KERNEL_DIR=/usr/src/linux KBUILD_OUTPUT=/lib/modules/3.10.25-gentoo/build 
    Using standalone build system.
    Makefile:167: Makefile.normal: No such file or directory
    make: *** No rule to make target `Makefile.normal'.  Stop.
     * ERROR: app-emulation/vmware-modules-279.0::gentoo failed (compile phase):
     *   emake failed
    -- snip --
    
    これはどうやらカーネルのソースツリーを参照しに行ったけれどもファイルが見つからなかったというものらしく、以下で無事 emerge できた。
    # FEATURES="-userpriv" emerge -av1 vmware-modules
    
    userpriv feature は emerge のプロセスをユーザ権限 (portage) で実行する機能で、portage ユーザに必要なパーミッションがない場合に上記のようなエラーで失敗するもよう。FEATURE="-userpriv" することにより emerge が root 権限で実行され、このパーミッション問題が解決した。
    検索しても直接関わる情報が見つからなかったのは、umask をデフォルトより厳しい値 (0077) に設定していたからと思われる。また、この他にもカーネルモジュールを emerge する場合には同様の問題が発生するだろう。

    ということで、今後の emerge で -userpriv されるように以下の設定を行った。
    # echo 'FEATURES="-userpriv"' >> /etc/portage/env/rootpriv.conf
    # ecoo 'app-emulation/vmware-modules rootpriv.conf' >> /etc/portage/package.env