Raspberry Pi 4上のclamonaccでOnAccessPrevention trueにする方法

clamav

約 11 分で読めます。

Raspberry Pi 4にclamonaccを入れ順調に使っていたのですが、OnAccessPreventionをtrueにしたらリアルタイムスキャンが全く動作しなくなってしまいました😥
この問題を自分なりに調べて解決したので紹介します🖥

clamonaccとは

恐らくこのページを見ているということはclamonaccをご存知と思いますが、一応。
Linux用オープンソースのアンチウィルスclamavのリアルタイムスキャン用プログラムです。

今回取り組む問題は、↑の記事でこのようにコメントしていたコレです。

OnAccessPreventionをtrueにすると、kernelの拡張機能であるFANOTIFYによる監視が動きます。

ですが、今は導入に以下の課題があり、入れることができません。
 ・Raspberry Pi OSのkernelはFANOTIFYが無効
 ・有効化したkernelで動かしてみたがclamonaccとclamdscanとの通信でエラーになる

これは今後トライしてみたいと思います。

OnAccessPreventionを有効にするとどうなるか

OnAccessPreventionはmanで見るとこんな感じ。
FANOTIFYによる防御機構が動きます。

OnAccessPrevention BOOL
       Enables fanotify blocking when malicious files are found.
       Default: disabled

ただ、デフォルトのRaspberry Pi OSに含まれるkernelではCONFIG_FANOTIFY_ACCESS_PERMISSIONSが無効のため、動かすことができません。

sudo modprobe configs
zcat /proc/config.gz | grep FANOTIFY_ACCESS_PERMISSIONS
# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set

CONFIG_FANOTIFY_ACCESS_PERMISSIONSを有効にする

そこで有効にしたkernelをビルドして入れることにします。
公式ページにkernelビルドの方法が書いてあるので従います。

Raspberry Pi Documentation - The Linux kernel
The official documentation for Raspberry Pi computers and microcontrollers
sudo apt install git bc bison flex libssl-dev make
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
export KERNEL=kernel7l
make bcm2711_defconfig

.configのCONFIG_LOCALVERSIONは一応変えておきます。
 CONFIG_LOCALVERSION=”-v7l-MY_CUSTOM_KERNEL”

以下でビルドからインストールまで行います。
Raspberry Pi 4で一時間くらいかかりました。

make -j4 zImage modules dtbs
sudo make modules_install
sudo cp arch/arm/boot/dts/.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img

再起動し、CONFIG_FANOTIFY_ACCESS_PERMISSIONSが有効になったことが確認できました。

sudo modprobe configs
zcat /proc/config.gz | grep FANOTIFY_ACCESS_PERMISSIONS
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y

OnAccessPreventionをtrueにしてみる

無事有効化されましたので、この状態でOnAccessPreventionをtrueにして、テストウィルスをダウンロードしてみましたが、以下の通りエラーになりスキャンされません。

ClamFanotif: attempting to feed consumer queue
ClamWorker: performing scanning on file '/var/www/html/nextcloud/index.html'
ERROR: ClamCom: TIMEOUT while waiting on socket (recv)
ClamClient: connection could not be established … return code 12

gdbでいろいろデバッグした結果、clamdへのスキャン依頼ができていないようです。

clamonacc起動時に–fdpassオプションを渡すと期待通り動いてくれました。

–fdpass自体は以下の通りとなっています。
clamd/clamonaccが別々のユーザーで動いているときに有効とありますが、自分の環境では両方ともrootだったので謎です。。。

--fdpass Pass filedescriptor to clamd (useful if clamd is running as a different user)

ちなみに–fdpassにより動くコードはこのあたり。
Unix Domain Socketを使うようにする具合ですかね。

clamonacc/client/client.c
cl_error_t onas_setup_client(struct onas_context **ctx)
{
(略)
if (!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled)) {
     if (onas_set_sock_only_once(*ctx) == CL_EWRITE) {
(略)
clamonacc/client/socket.c
cl_error_t onas_set_sock_only_once(struct onas_context *ctx)
{
(略)
if (onas_sock.written != 1) {
     if (((opt =
               optget(ctx->clamdopts, "LocalSocket"))
              ->enabled) &&
         optget(ctx->opts, "fdpass")->enabled) {
         memset((void *)&onas_sock, 0, sizeof(onas_sock));
         onas_sock.sock.sun_family = AF_UNIX;
         strncpy(onas_sock.sock.sun_path, opt->strarg, sizeof(onas_sock.sock.sun_path));
         onas_sock.sock.sun_path[sizeof(onas_sock.sock.sun_path) - 1] = '\0';
         onas_sock.written                                            = 1;
         return CL_SUCCESS;
     }
 }

これでOnAccessPrevention自体は動くようになったのですが、パフォーマンスが激落ちです。
というのも、読み取りファイルすらスキャンするため。

この記事で少し解説しています。

OnAccessPreventionがfalseなら↑の記事で紹介したパッチが使えるのですが、trueの場合は対応するマスクがないので使えません。ということで諦め。

Chromebookや最近のPCなら問題ないのでしょうが、Raspberry Pi 4では力不足💪⤵
結局OnAccessPreventionはfalseで使うことにしました😅

終わりに

いかがでしたか。

OnAccessPreventionがtrueの場合に–fdpassを指定しなければならないのは仕様なのかバグなのか、はっきりしていませんが、ひとまず動かないという疑問は解けたので良しとします。

また暇なときにでも解析するかもしれません😀

Comments

タイトルとURLをコピーしました