{"componentChunkName":"component---src-templates-post-template-js","path":"/clamav-onaccess-scanning-en","result":{"data":{"markdownRemark":{"id":"0271b640-d212-5c20-a7b1-fb898371ef53","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/clamav-onaccess-scanning\">original page</a>.</p>\n</blockquote>\n<p>Out of the blue, but at the online market for Technical Book Fest 17, which has been running since 11/2, I am distributing a free technical doujin book titled <em>A part of Anti-Virus  -Learning Windows filesystem minifilter driver from public sample code-</em>. </p>\n<p>In that book, I explain how AntiVirus software for Windows uses filesystem minifilter drivers for real-time file scanning (On-Access scanning).</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 225px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/618c23cecd7be79bebc2e882b5af1777/3684f/sJkxmU1rbhDeuKQ9qXjEZG.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 142.22222222222223%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAIAAADuuAg3AAAACXBIWXMAAAsTAAALEwEAmpwYAAADm0lEQVQ4y5VUWU8TURTmQYOyKEWlEUGE0r0zXWam01JaWjotZbOlIAGCW0EjqOxgsJZoBNRIIqBGwRhjDA8uTyb6wKPRFxN/gjEiBjUxEiU+qIDfzLAJdbs5mZx75nz33Pvd79wYgguonCXZuT65vfDfTeEoIj2BGLWzWKJhE5X0JhWzWW1O0rBwkjRm3oQpgpv5CCv+WjJ1XnGMMq84WWsRAPwSG2QGfGOz9HA2yIyxMsPGbKMYj83Uw+HXEowHqwQwJkjSuErK6o5rXKXNPef8oaNVje1Nkd76zojOvTvUFu7qHaAKy5EmbmcZjPn6XURZfdOlG7ede/ZHLg73Dl0fHbs/OnavsqHd4KsYunlnZOx+GutOUNKrwZgkqpgM1i3L8UqN9iyrlycmp0Ce60unnalEjoELyC2erVG3LdGy6zKImmMdLafP9Q+PtPT0N0T6GIu7SUF2aE1XCVOrkuxSG1sIJmE1WMdXjpObOnsv9l8evXJrDAduDJ9lC4InNMYmgrlC0mdIpo+kwwS1aW1lsC3RWrborPjGKyg4CILhJMRxEUo6WUFJ1YxUY14D1llBQ7zchOI7aCc4T9HnSg32dMYl1eduJXMQzLB4kglbnIJKUFCiIgSwsxjs7TTnKxyFWVYP5Su3lFaRbr+xIGjwBuHoOb/eE7D5q1WOokwLBy6x7oJIUBlgzDOtHvzDKqmUE7RvNzlQfxtpS2fyEdzFcqmUI412Ig3xZTAIg3TihS3hiwvfKDMiA9ogOX+K3haXbcRd4C/Sft324j2LV79Nb7MHa2GVR9rODl7rGx6pbuzA1BHcK+52Qe2r2EYU9BKcP9R+6u7Dxy9fT8xizM29mph88GgcIqUKK6B5KCI6OC7bpHQU1XVEPn6anp+f/zE7C4PzeWamofsMToHjSH5XOUFBpzGummOdr95MAjMnDDiTU+/2NXdnWr1gJPq2xRDkgcYaf/IMmG/fMX7Aefr8RfnhZjC/lBYFjC2h4+xltd3nL01//jIvjJmvX3sGhtFqkNBS2eiV4UBwJfsbu/oGJt5OTb3/EL4wuPvgUegsUblcNjpYfE/g2IN7D7SeDLWH8yr2geGlNv4TeBHPgFgoUWYrwEFWXu9fwLxUSBtMIrwwkJpkDfJPYF/tIa4q5KmuswVqcGCDt+w/Kq9MFR/d31bewr8ki2/1srErzLzWFltSbRY75r8MwBitqxS6E5rW/e+WwXK6/NKfscmXgv5Rs9oAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/618c23cecd7be79bebc2e882b5af1777/d7e55/sJkxmU1rbhDeuKQ9qXjEZG.webp 225w\"\n              sizes=\"(max-width: 225px) 100vw, 225px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/618c23cecd7be79bebc2e882b5af1777/3684f/sJkxmU1rbhDeuKQ9qXjEZG.png 225w\"\n            sizes=\"(max-width: 225px) 100vw, 225px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/618c23cecd7be79bebc2e882b5af1777/3684f/sJkxmU1rbhDeuKQ9qXjEZG.png\"\n            alt=\"img\"\n            title=\"img\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Reference: <a href=\"https://techbookfest.org/product/iFrVq6PX0PPJhivrGzhi32?productVariantID=6UbwYGmwy2vuS7CnnCtpPg&#x26;utm_campaign=share&#x26;utm_medium=social&#x26;utm_source=twitter\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">A part of Anti-Virus：Frog’s Bookshelf</a></p>\n<p>As with <a href=\"https://techbookfest.org/product/bnaHM8sVz6AfEiF8jgpELj?productVariantID=bXvgf8g2KDpRRVJ9pBZJXH\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Magical WinDbg Vol 1/2</a>, this one is also available for free due to various circumstances, so please feel free to pick it up.</p>\n<p>In this article, as a kind of extra chapter to that book, I will briefly explain fanotify, the kernel framework used by AntiVirus software for Linux for real-time file scanning (On-Access scanning).</p>\n<p>ClamAV for Linux implements On-Access scanning using fanotify, which is supported by the Linux kernel.</p>\n<p>Major commercial AntiVirus products for Linux also use fanotify to implement On-Access scanning just like ClamAV, so understanding ClamAV at the source-code level should also be useful for understanding how those commercial AntiVirus products behave.</p>\n<p>Reference: <a href=\"https://man7.org/linux/man-pages/man7/fanotify.7.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">fanotify(7) - Linux manual page</a></p>\n<p>Reference: <a href=\"https://docs.clamav.net/manual/OnAccess.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">On-Access Scanning - ClamAV Documentation</a></p>\n<p>In this article, I will give a rough summary of how On-Access scanning for Linux AntiVirus software behaves when built on fanotify, using ClamAV as the example.</p>\n<p>In this article, I refer to the source code of ClamAV 0.104.</p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li>\n<p><a href=\"#creating-a-fanotify-test-program\">Creating a fanotify test program</a></p>\n<ul>\n<li><a href=\"#what-is-fanotify\">What is fanotify?</a></li>\n<li><a href=\"#creating-a-sample-fanotify-program\">Creating a sample fanotify program</a></li>\n<li><a href=\"#denying-operations-on-a-specific-file\">Denying operations on a specific file</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#reading-clamonacc\">Reading clamonacc</a></p>\n<ul>\n<li><a href=\"#checking-the-implementation-of-the-clamonacc-main-function\">Checking the implementation of the clamonacc main function</a></li>\n<li><a href=\"#initialization\">Initialization</a></li>\n<li><a href=\"#getting-command-line-arguments\">Getting command-line arguments</a></li>\n<li><a href=\"#registering-fanotify\">Registering fanotify</a></li>\n<li><a href=\"#setting-up-signal-handling\">Setting up signal handling</a></li>\n<li><a href=\"#waiting-for-scan-events\">Waiting for scan events</a></li>\n<li><a href=\"#monitoring-the-scan-queue\">Monitoring the scan queue</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n</ul>\n<h2 id=\"creating-a-fanotify-test-program\" style=\"position:relative;\"><a href=\"#creating-a-fanotify-test-program\" aria-label=\"creating a fanotify test program permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a fanotify test program</h2>\n<p>Before looking at ClamAV’s implementation, I first wrote a test program to understand how fanotify itself works.</p>\n<h3 id=\"what-is-fanotify\" style=\"position:relative;\"><a href=\"#what-is-fanotify\" aria-label=\"what is fanotify permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is fanotify?</h3>\n<p>Like inotify, the framework for monitoring filesystem events that has existed since Linux kernel 2.6.13, fanotify can notify userspace about filesystem events in the system, and it can also allow or deny those operations. (Apparently it was preceded by an even older mechanism called dnotify.)</p>\n<p>Reference: <a href=\"https://lpc.events/event/18/contributions/1717/attachments/1648/3404/fanotify.pdf?form=MG0AV3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Linux file system notification subsystem</a></p>\n<p>fanotify was added in Linux kernel 2.6.36 and enabled in 2.6.37.</p>\n<p>Since then, various features and bug fixes seem to have been added.</p>\n<p>As far as I could tell from the Linux-kernel-related books I own, fanotify is barely mentioned. But when you read an LWN.net newsletter article from 2009, you can see that fanotify was added in response to requests from AntiVirus vendors and customers for a practical way to implement On-Access scanning.</p>\n<blockquote>\n<p>So it’s back to that time.  I’m not quite sure how to present fanotify.\nI can start sending patches (they are available), but this message is just going to be a re-into, what questions and problems are still out there?</p>\n<p>Long ago the anti-malware vendors started asking the community for a reasonable way to do on access file scanning, historically they have used syscall table rewrites and binary LSM hook hacks to get their information. </p>\n<p>Customers and Linux users keep demanding this stuff and in an effort give them a supportable method to use these products I have been working to develop fanotify.</p>\n<p>fanotify provides two things:</p>\n<ol>\n<li>a new notification system, sorta like inotify, only instead of an arbitrary ‘watch descriptor’ which userspace has to know how to map back to an object on the filesystem, fanotify provides an open read-only fd back to the original object.  It should be noted that the set of fanotify events is much smaller than the set of inotify events.</li>\n<li>an access system in which processes may be blocked until the fanotify userspace listener has decided if the operation should be allowed. </li>\n</ol>\n</blockquote>\n<p>Reference: <a href=\"https://lwn.net/Articles/339253/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">fanotify: the fscking all notification system [LWN.net]</a></p>\n<p>Note that fanotify is implemented only as an interface for On-Access scanning by AntiVirus software; fanotify itself does not detect or block malware.</p>\n<p>The following threads were also helpful references for discussions related to fanotify’s design and implementation.</p>\n<p>Reference: <a href=\"https://groups.google.com/g/fa.linux.kernel/c/UQU5_8OYy3A/m/ne4osM_-hnAJ\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Re: [malware-list] scanner interface proposal was: [TALPA] Intro to a linux interface for on access scanning</a></p>\n<p>Reference: <a href=\"https://groups.google.com/g/fa.linux.kernel/c/cRFNvHhmtMs/m/iweECb_p0xUJ\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">TALPA - a threat model? well sorta.</a></p>\n<h3 id=\"creating-a-sample-fanotify-program\" style=\"position:relative;\"><a href=\"#creating-a-sample-fanotify-program\" aria-label=\"creating a sample fanotify program permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Creating a sample fanotify program</h3>\n<p>To better understand fanotify, I decided to create a test program and verify its behavior.</p>\n<p>The code below is a slightly customized version of the sample code introduced in the following manual.</p>\n<p>Reference: <a href=\"https://manpages.ubuntu.com/manpages/focal/ja/man7/fanotify.7.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Ubuntu Manpage: fanotify - monitor filesystem events</a></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token comment\">/* Define _GNU_SOURCE, Otherwise we don't get O_LARGEFILE */</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">_GNU_SOURCE</span></span>\n\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdio.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;signal.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;unistd.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdlib.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;poll.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;errno.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;limits.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sys/stat.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sys/signalfd.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;fcntl.h></span></span>\n\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;linux/fanotify.h></span></span>\n\n<span class=\"token comment\">/* Structure to keep track of monitored directories */</span>\n<span class=\"token keyword\">typedef</span> <span class=\"token keyword\">struct</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">/* Path of the directory */</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>path<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token class-name\">monitored_t</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* Size of buffer to use when reading fanotify events */</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">FANOTIFY_BUFFER_SIZE</span> <span class=\"token expression\"><span class=\"token number\">8192</span></span></span>\n\n<span class=\"token comment\">/* Enumerate list of FDs to poll */</span>\n<span class=\"token keyword\">enum</span>\n<span class=\"token punctuation\">{</span>\n    FD_POLL_SIGNAL <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n    FD_POLL_FANOTIFY<span class=\"token punctuation\">,</span>\n    FD_POLL_MAX\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* Setup fanotify notifications (FAN) mask. All these defined in fanotify.h. */</span>\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">uint64_t</span> event_mask <span class=\"token operator\">=</span>\n    <span class=\"token punctuation\">(</span>FAN_ACCESS <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File accessed */</span>\n     FAN_MODIFY <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File modified */</span>\n     FAN_CLOSE_WRITE <span class=\"token operator\">|</span>    <span class=\"token comment\">/* Writtable file closed */</span>\n     FAN_CLOSE_NOWRITE <span class=\"token operator\">|</span>  <span class=\"token comment\">/* Unwrittable file closed */</span>\n     FAN_OPEN <span class=\"token operator\">|</span>           <span class=\"token comment\">/* File was opened */</span>\n     FAN_ONDIR <span class=\"token operator\">|</span>          <span class=\"token comment\">/* We want to be reported of events in the directory */</span>\n     FAN_EVENT_ON_CHILD<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">/* We want to be reported of events in files of the directory */</span>\n\n<span class=\"token comment\">/* Array of directories being monitored */</span>\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">monitored_t</span> <span class=\"token operator\">*</span>monitors<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span> n_monitors<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>\n<span class=\"token function\">get_program_name_from_pid</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> pid<span class=\"token punctuation\">,</span>\n                          <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>buffer<span class=\"token punctuation\">,</span>\n                          <span class=\"token class-name\">size_t</span> buffer_size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> fd<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">ssize_t</span> len<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>aux<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Try to get program name by PID */</span>\n    <span class=\"token function\">sprintf</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"/proc/%d/cmdline\"</span><span class=\"token punctuation\">,</span> pid<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fd <span class=\"token operator\">=</span> <span class=\"token function\">open</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> O_RDONLY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Read file contents into buffer */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>len <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> buffer_size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    buffer<span class=\"token punctuation\">[</span>len<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n    aux <span class=\"token operator\">=</span> <span class=\"token function\">strstr</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"^@\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>aux<span class=\"token punctuation\">)</span>\n        <span class=\"token operator\">*</span>aux <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> buffer<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>\n<span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fd<span class=\"token punctuation\">,</span>\n                      <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>buffer<span class=\"token punctuation\">,</span>\n                      <span class=\"token class-name\">size_t</span> buffer_size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">ssize_t</span> len<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fd <span class=\"token operator\">&lt;=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">sprintf</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"/proc/self/fd/%d\"</span><span class=\"token punctuation\">,</span> fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>len <span class=\"token operator\">=</span> <span class=\"token function\">readlink</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> buffer_size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    buffer<span class=\"token punctuation\">[</span>len<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> buffer<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">event_process</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span>event<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">char</span> path<span class=\"token punctuation\">[</span>PATH_MAX<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Received event in path '%s'\"</span><span class=\"token punctuation\">,</span>\n           <span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">,</span>\n                                 path<span class=\"token punctuation\">,</span>\n                                 PATH_MAX<span class=\"token punctuation\">)</span>\n               <span class=\"token operator\">?</span> path\n               <span class=\"token operator\">:</span> <span class=\"token string\">\"unknown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" pid=%d (%s): \\n\"</span><span class=\"token punctuation\">,</span>\n           event<span class=\"token operator\">-></span>pid<span class=\"token punctuation\">,</span>\n           <span class=\"token punctuation\">(</span><span class=\"token function\">get_program_name_from_pid</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>pid<span class=\"token punctuation\">,</span>\n                                      path<span class=\"token punctuation\">,</span>\n                                      PATH_MAX<span class=\"token punctuation\">)</span>\n                <span class=\"token operator\">?</span> path\n                <span class=\"token operator\">:</span> <span class=\"token string\">\"unknown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_OPEN<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_OPEN\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_ACCESS<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_ACCESS\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_MODIFY<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_MODIFY\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_CLOSE_WRITE<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_CLOSE_WRITE\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_CLOSE_NOWRITE<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_CLOSE_NOWRITE\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">fflush</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stdout</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span>\n<span class=\"token function\">shutdown_fanotify</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n_monitors<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">/* Remove the mark, using same event mask as when creating it */</span>\n        <span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span>\n                      FAN_MARK_REMOVE<span class=\"token punctuation\">,</span>\n                      event_mask<span class=\"token punctuation\">,</span>\n                      AT_FDCWD<span class=\"token punctuation\">,</span>\n                      monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>monitors<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span>\n<span class=\"token function\">initialize_fanotify</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span>\n                    <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>argv<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Create new fanotify device */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fanotify_fd <span class=\"token operator\">=</span> <span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span>\n                                     O_RDONLY <span class=\"token operator\">|</span> O_LARGEFILE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't setup new fanotify device: %s\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Allocate array of monitor setups */</span>\n    n_monitors <span class=\"token operator\">=</span> argc <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    monitors <span class=\"token operator\">=</span> <span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span>n_monitors <span class=\"token operator\">*</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">monitored_t</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Loop all input directories, setting up marks */</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n_monitors<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path <span class=\"token operator\">=</span> <span class=\"token function\">strdup</span><span class=\"token punctuation\">(</span>argv<span class=\"token punctuation\">[</span>i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token comment\">/* Add new fanotify mark */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span>\n                          FAN_MARK_ADD <span class=\"token operator\">|</span> FAN_MARK_MOUNT<span class=\"token punctuation\">,</span>\n                          event_mask<span class=\"token punctuation\">,</span>\n                          AT_FDCWD<span class=\"token punctuation\">,</span>\n                          monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"Couldn't add monitor in directory '%s': '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                    monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Started monitoring directory '%s'...\\n\"</span><span class=\"token punctuation\">,</span>\n               monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> fanotify_fd<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span>\n<span class=\"token function\">shutdown_signals</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>signal_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span>\n<span class=\"token function\">initialize_signals</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">sigset_t</span> sigmask<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* We want to handle SIGINT and SIGTERM in the signal_fd, so we block them. */</span>\n    <span class=\"token function\">sigemptyset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaddset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> SIGINT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaddset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> SIGTERM<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">sigprocmask</span><span class=\"token punctuation\">(</span>SIG_BLOCK<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't block signals: '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Get new FD to read signals from it */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>signal_fd <span class=\"token operator\">=</span> <span class=\"token function\">signalfd</span><span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't setup signal FD: '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> signal_fd<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span>\n         <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>argv<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">pollfd</span> fds<span class=\"token punctuation\">[</span>FD_POLL_MAX<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Input arguments... */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>argc <span class=\"token operator\">&lt;</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Usage: %s directory1 [directory2 ...]\\n\"</span><span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Initialize signals FD */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>signal_fd <span class=\"token operator\">=</span> <span class=\"token function\">initialize_signals</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't initialize signals\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Initialize fanotify FD and the marks */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fanotify_fd <span class=\"token operator\">=</span> <span class=\"token function\">initialize_fanotify</span><span class=\"token punctuation\">(</span>argc<span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't initialize fanotify\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Setup polling */</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> signal_fd<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>events <span class=\"token operator\">=</span> POLLIN<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> fanotify_fd<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>events <span class=\"token operator\">=</span> POLLIN<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Now loop */</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">/* Block until there is something to be read */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">poll</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">,</span> FD_POLL_MAX<span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"Couldn't poll(): '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token comment\">/* Signal received? */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>revents <span class=\"token operator\">&amp;</span> POLLIN<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">struct</span> <span class=\"token class-name\">signalfd_siginfo</span> fdsi<span class=\"token punctuation\">;</span>\n\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>fdsi<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't read signal, wrong size read\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n\n            <span class=\"token comment\">/* Break loop if we got the expected signal */</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">.</span>ssi_signo <span class=\"token operator\">==</span> SIGINT <span class=\"token operator\">||</span> fdsi<span class=\"token punctuation\">.</span>ssi_signo <span class=\"token operator\">==</span> SIGTERM<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Received unexpected signal\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token comment\">/* fanotify event received? */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>revents <span class=\"token operator\">&amp;</span> POLLIN<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">char</span> buffer<span class=\"token punctuation\">[</span>FANOTIFY_BUFFER_SIZE<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n            <span class=\"token class-name\">ssize_t</span> length<span class=\"token punctuation\">;</span>\n\n            <span class=\"token comment\">/* Read from the FD. It will read all events available up to\n             * the given buffer size. */</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>length <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> FANOTIFY_BUFFER_SIZE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span>metadata<span class=\"token punctuation\">;</span>\n\n                metadata <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>buffer<span class=\"token punctuation\">;</span>\n                <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAN_EVENT_OK</span><span class=\"token punctuation\">(</span>metadata<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token function\">event_process</span><span class=\"token punctuation\">(</span>metadata<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>metadata<span class=\"token operator\">-></span>fd <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n                        <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>metadata<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                    metadata <span class=\"token operator\">=</span> <span class=\"token function\">FAN_EVENT_NEXT</span><span class=\"token punctuation\">(</span>metadata<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Clean exit */</span>\n    <span class=\"token function\">shutdown_fanotify</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">shutdown_signals</span><span class=\"token punctuation\">(</span>signal_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Exiting fanotify example...\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> EXIT_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nI will not go into a detailed explanation of the sample above because it is not the main point here<span class=\"token punctuation\">,</span> but it initializes fanotify with settings that are almost the same as ClamAV's<span class=\"token punctuation\">,</span> as shown below<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token comment\">/* Setup fanotify notifications (FAN) mask. All these defined in fanotify.h. */</span>\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">uint64_t</span> event_mask <span class=\"token operator\">=</span>\n    <span class=\"token punctuation\">(</span>FAN_ACCESS <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File accessed */</span>\n     FAN_MODIFY <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File modified */</span>\n     FAN_CLOSE_WRITE <span class=\"token operator\">|</span>    <span class=\"token comment\">/* Writtable file closed */</span>\n     FAN_CLOSE_NOWRITE <span class=\"token operator\">|</span>  <span class=\"token comment\">/* Unwrittable file closed */</span>\n     FAN_OPEN <span class=\"token operator\">|</span>           <span class=\"token comment\">/* File was opened */</span>\n     FAN_ONDIR <span class=\"token operator\">|</span>          <span class=\"token comment\">/* We want to be reported of events in the directory */</span>\n     FAN_EVENT_ON_CHILD<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">/* We want to be reported of events in files of the directory */</span>\n\n<span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span> O_RDONLY <span class=\"token operator\">|</span> O_LARGEFILE<span class=\"token punctuation\">)</span>\n    \n<span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span>\n              FAN_MARK_ADD <span class=\"token operator\">|</span> FAN_MARK_MOUNT<span class=\"token punctuation\">,</span>\n              event_mask<span class=\"token punctuation\">,</span>\n              AT_FDCWD<span class=\"token punctuation\">,</span>\n              monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span>\n\nIf you build this source code and run the resulting program with a mount point as the argument<span class=\"token punctuation\">,</span> you can receive fanotify notifications when directory or file accesses occur within that mount point<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241027211958055</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241027211958055.</span>png<span class=\"token punctuation\">)</span>\n\nOne especially confusing part here was how `FAN_MARK_MOUNT` behaves<span class=\"token punctuation\">.</span>\n\nWhen `FAN_MARK_MOUNT` is specified in the `fanotify_mark` function<span class=\"token punctuation\">,</span> fanotify appears to monitor all directories and files inside the <span class=\"token string\">\"mount point\"</span> received via the path argument<span class=\"token punctuation\">.</span>\n\nIn other words<span class=\"token punctuation\">,</span> the object being monitored here seems to be the mount point itself<span class=\"token punctuation\">,</span> not a <span class=\"token string\">\"directory\"</span> in the same sense as a Windows folder<span class=\"token punctuation\">.</span>\n\nIn the environment where I first tested this<span class=\"token punctuation\">,</span> the `<span class=\"token operator\">/</span>home` directory existed under the same mount point as directories such as `<span class=\"token operator\">/</span>usr`<span class=\"token punctuation\">,</span> so even <span class=\"token keyword\">if</span> I specified `<span class=\"token operator\">/</span>home<span class=\"token operator\">/</span>user` as the monitor target<span class=\"token punctuation\">,</span> I still received access events <span class=\"token keyword\">for</span> every file in that same mount point<span class=\"token punctuation\">,</span> such as `<span class=\"token operator\">/</span>usr<span class=\"token operator\">/</span>file`<span class=\"token punctuation\">.</span>\n\nIn practice<span class=\"token punctuation\">,</span> after following the steps in the article below to move `<span class=\"token operator\">/</span>home` to a separate partition and then editing `<span class=\"token operator\">/</span>etc<span class=\"token operator\">/</span>fstab` to assign `<span class=\"token operator\">/</span>home` its own mount point<span class=\"token punctuation\">,</span> I was able to monitor only accesses to directories and files under `<span class=\"token operator\">/</span>home` with fanotify<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>Moving an in<span class=\"token operator\">-</span>use home directory to another partition on <span class=\"token function\">Ubuntu</span> <span class=\"token punctuation\">(</span>no LiveUSB required<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> kamocyc’s blog<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//kamocyc.hatenablog.com/entry/2019/10/26/132015)</span>\n\nIf you want to monitor operations only on a specific directory or file<span class=\"token punctuation\">,</span> it seems better to specify just `FAN_MARK_ADD` rather than `FAN_MARK_MOUNT`<span class=\"token punctuation\">.</span>\n\n### Denying operations on a specific file\n\nOnce I could receive filesystem events with fanotify<span class=\"token punctuation\">,</span> I next rewrote the code so that only operations on a specific file would be denied<span class=\"token punctuation\">.</span>\n\nThe number of changes is small<span class=\"token punctuation\">,</span> but I will include the full source code below<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token comment\">/* Define _GNU_SOURCE, Otherwise we don't get O_LARGEFILE */</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">_GNU_SOURCE</span></span>\n\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdio.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;signal.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;unistd.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdlib.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;poll.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;errno.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;limits.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sys/stat.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sys/signalfd.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;fcntl.h></span></span>\n\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sys/fanotify.h></span></span>\n\n<span class=\"token comment\">/* Structure to keep track of monitored directories */</span>\n<span class=\"token keyword\">typedef</span> <span class=\"token keyword\">struct</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">/* Path of the directory */</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>path<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token class-name\">monitored_t</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* Size of buffer to use when reading fanotify events */</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">FANOTIFY_BUFFER_SIZE</span> <span class=\"token expression\"><span class=\"token number\">8192</span></span></span>\n\n<span class=\"token comment\">/* Enumerate list of FDs to poll */</span>\n<span class=\"token keyword\">enum</span>\n<span class=\"token punctuation\">{</span>\n    FD_POLL_SIGNAL <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n    FD_POLL_FANOTIFY<span class=\"token punctuation\">,</span>\n    FD_POLL_MAX\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/* Setup fanotify notifications (FAN) mask. All these defined in fanotify.h. */</span>\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">uint64_t</span> event_mask <span class=\"token operator\">=</span>\n    <span class=\"token punctuation\">(</span>FAN_OPEN_PERM <span class=\"token operator\">|</span>\n     FAN_ACCESS <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File accessed */</span>\n     FAN_MODIFY <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File modified */</span>\n     FAN_CLOSE_WRITE <span class=\"token operator\">|</span>    <span class=\"token comment\">/* Writtable file closed */</span>\n     FAN_CLOSE_NOWRITE <span class=\"token operator\">|</span>  <span class=\"token comment\">/* Unwrittable file closed */</span>\n     FAN_OPEN <span class=\"token operator\">|</span>           <span class=\"token comment\">/* File was opened */</span>\n     FAN_ONDIR <span class=\"token operator\">|</span>          <span class=\"token comment\">/* We want to be reported of events in the directory */</span>\n     FAN_EVENT_ON_CHILD<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">/* We want to be reported of events in files of the directory */</span>\n\n<span class=\"token comment\">/* Array of directories being monitored */</span>\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">monitored_t</span> <span class=\"token operator\">*</span>monitors<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span> n_monitors<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>\n<span class=\"token function\">get_program_name_from_pid</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> pid<span class=\"token punctuation\">,</span>\n                          <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>buffer<span class=\"token punctuation\">,</span>\n                          <span class=\"token class-name\">size_t</span> buffer_size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> fd<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">ssize_t</span> len<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>aux<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Try to get program name by PID */</span>\n    <span class=\"token function\">sprintf</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"/proc/%d/cmdline\"</span><span class=\"token punctuation\">,</span> pid<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fd <span class=\"token operator\">=</span> <span class=\"token function\">open</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> O_RDONLY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Read file contents into buffer */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>len <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> buffer_size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    buffer<span class=\"token punctuation\">[</span>len<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n    aux <span class=\"token operator\">=</span> <span class=\"token function\">strstr</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"^@\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>aux<span class=\"token punctuation\">)</span>\n        <span class=\"token operator\">*</span>aux <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> buffer<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>\n<span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fd<span class=\"token punctuation\">,</span>\n                      <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>buffer<span class=\"token punctuation\">,</span>\n                      <span class=\"token class-name\">size_t</span> buffer_size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">ssize_t</span> len<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fd <span class=\"token operator\">&lt;=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">sprintf</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> <span class=\"token string\">\"/proc/self/fd/%d\"</span><span class=\"token punctuation\">,</span> fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>len <span class=\"token operator\">=</span> <span class=\"token function\">readlink</span><span class=\"token punctuation\">(</span>buffer<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> buffer_size <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n\n    buffer<span class=\"token punctuation\">[</span>len<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'\\0'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> buffer<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">event_process</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">,</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span>event<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">char</span> path<span class=\"token punctuation\">[</span>PATH_MAX<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Received event in path '%s'\"</span><span class=\"token punctuation\">,</span>\n           <span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">,</span>\n                                 path<span class=\"token punctuation\">,</span>\n                                 PATH_MAX<span class=\"token punctuation\">)</span>\n               <span class=\"token operator\">?</span> path\n               <span class=\"token operator\">:</span> <span class=\"token string\">\"unknown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" pid=%d (%s): \\n\"</span><span class=\"token punctuation\">,</span>\n           event<span class=\"token operator\">-></span>pid<span class=\"token punctuation\">,</span>\n           <span class=\"token punctuation\">(</span><span class=\"token function\">get_program_name_from_pid</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>pid<span class=\"token punctuation\">,</span>\n                                      path<span class=\"token punctuation\">,</span>\n                                      PATH_MAX<span class=\"token punctuation\">)</span>\n                <span class=\"token operator\">?</span> path\n                <span class=\"token operator\">:</span> <span class=\"token string\">\"unknown\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_OPEN<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_OPEN\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_ACCESS<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_ACCESS\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_MODIFY<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_MODIFY\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_CLOSE_WRITE<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_CLOSE_WRITE\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>mask <span class=\"token operator\">&amp;</span> FAN_CLOSE_NOWRITE<span class=\"token punctuation\">)</span>\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\\tFAN_CLOSE_NOWRITE\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">fflush</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stdout</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_response</span> response<span class=\"token punctuation\">;</span>\n    response<span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">strcmp</span><span class=\"token punctuation\">(</span><span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">,</span>\n                                     path<span class=\"token punctuation\">,</span>\n                                     PATH_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n               <span class=\"token string\">\"/home/rana/eicar\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        response<span class=\"token punctuation\">.</span>response <span class=\"token operator\">=</span> FAN_DENY<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">else</span>\n    <span class=\"token punctuation\">{</span>\n        response<span class=\"token punctuation\">.</span>response <span class=\"token operator\">=</span> FAN_ALLOW<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">write</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>response<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span>\n<span class=\"token function\">shutdown_fanotify</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n_monitors<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">/* Remove the mark, using same event mask as when creating it */</span>\n        <span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span>\n                      FAN_MARK_REMOVE<span class=\"token punctuation\">,</span>\n                      event_mask<span class=\"token punctuation\">,</span>\n                      AT_FDCWD<span class=\"token punctuation\">,</span>\n                      monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>monitors<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span>\n<span class=\"token function\">initialize_fanotify</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span>\n                    <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>argv<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Create new fanotify device */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fanotify_fd <span class=\"token operator\">=</span> <span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span>\n                                     O_RDONLY <span class=\"token operator\">|</span> O_LARGEFILE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't setup new fanotify device: %s\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Allocate array of monitor setups */</span>\n    n_monitors <span class=\"token operator\">=</span> argc <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    monitors <span class=\"token operator\">=</span> <span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span>n_monitors <span class=\"token operator\">*</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">monitored_t</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Loop all input directories, setting up marks */</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n_monitors<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path <span class=\"token operator\">=</span> <span class=\"token function\">strdup</span><span class=\"token punctuation\">(</span>argv<span class=\"token punctuation\">[</span>i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token comment\">/* Add new fanotify mark */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span>\n                          FAN_MARK_ADD <span class=\"token operator\">|</span> FAN_MARK_MOUNT<span class=\"token punctuation\">,</span>\n                          event_mask<span class=\"token punctuation\">,</span>\n                          AT_FDCWD<span class=\"token punctuation\">,</span>\n                          monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"Couldn't add monitor in directory '%s': '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                    monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Started monitoring directory '%s'...\\n\"</span><span class=\"token punctuation\">,</span>\n               monitors<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> fanotify_fd<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span>\n<span class=\"token function\">shutdown_signals</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>signal_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span>\n<span class=\"token function\">initialize_signals</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">sigset_t</span> sigmask<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* We want to handle SIGINT and SIGTERM in the signal_fd, so we block them. */</span>\n    <span class=\"token function\">sigemptyset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaddset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> SIGINT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaddset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> SIGTERM<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">sigprocmask</span><span class=\"token punctuation\">(</span>SIG_BLOCK<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't block signals: '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Get new FD to read signals from it */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>signal_fd <span class=\"token operator\">=</span> <span class=\"token function\">signalfd</span><span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>sigmask<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"Couldn't setup signal FD: '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> signal_fd<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span>\n         <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>argv<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> signal_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> fanotify_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">pollfd</span> fds<span class=\"token punctuation\">[</span>FD_POLL_MAX<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Input arguments... */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>argc <span class=\"token operator\">&lt;</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Usage: %s directory1 [directory2 ...]\\n\"</span><span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Initialize signals FD */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>signal_fd <span class=\"token operator\">=</span> <span class=\"token function\">initialize_signals</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't initialize signals\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Initialize fanotify FD and the marks */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>fanotify_fd <span class=\"token operator\">=</span> <span class=\"token function\">initialize_fanotify</span><span class=\"token punctuation\">(</span>argc<span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't initialize fanotify\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Setup polling */</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> signal_fd<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>events <span class=\"token operator\">=</span> POLLIN<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> fanotify_fd<span class=\"token punctuation\">;</span>\n    fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>events <span class=\"token operator\">=</span> POLLIN<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* Now loop */</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">/* Block until there is something to be read */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">poll</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">,</span> FD_POLL_MAX<span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"Couldn't poll(): '%s'\\n\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token comment\">/* Signal received? */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>revents <span class=\"token operator\">&amp;</span> POLLIN<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">struct</span> <span class=\"token class-name\">signalfd_siginfo</span> fdsi<span class=\"token punctuation\">;</span>\n\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_SIGNAL<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>fdsi<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Couldn't read signal, wrong size read\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span>EXIT_FAILURE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n\n            <span class=\"token comment\">/* Break loop if we got the expected signal */</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fdsi<span class=\"token punctuation\">.</span>ssi_signo <span class=\"token operator\">==</span> SIGINT <span class=\"token operator\">||</span> fdsi<span class=\"token punctuation\">.</span>ssi_signo <span class=\"token operator\">==</span> SIGTERM<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n\n            <span class=\"token function\">fprintf</span><span class=\"token punctuation\">(</span><span class=\"token constant\">stderr</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Received unexpected signal\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token comment\">/* fanotify event received? */</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>revents <span class=\"token operator\">&amp;</span> POLLIN<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">char</span> buffer<span class=\"token punctuation\">[</span>FANOTIFY_BUFFER_SIZE<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n            <span class=\"token class-name\">ssize_t</span> length<span class=\"token punctuation\">;</span>\n\n            <span class=\"token comment\">/* Read from the FD. It will read all events available up to\n             * the given buffer size. */</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>length <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fds<span class=\"token punctuation\">[</span>FD_POLL_FANOTIFY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>fd<span class=\"token punctuation\">,</span> buffer<span class=\"token punctuation\">,</span> FANOTIFY_BUFFER_SIZE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span>metadata<span class=\"token punctuation\">;</span>\n\n                metadata <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>buffer<span class=\"token punctuation\">;</span>\n                <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAN_EVENT_OK</span><span class=\"token punctuation\">(</span>metadata<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token function\">event_process</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span> metadata<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>metadata<span class=\"token operator\">-></span>fd <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n                        <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>metadata<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                    metadata <span class=\"token operator\">=</span> <span class=\"token function\">FAN_EVENT_NEXT</span><span class=\"token punctuation\">(</span>metadata<span class=\"token punctuation\">,</span> length<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">/* Clean exit */</span>\n    <span class=\"token function\">shutdown_fanotify</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">shutdown_signals</span><span class=\"token punctuation\">(</span>signal_fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Exiting fanotify example...\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> EXIT_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nThe first key point is that the `FAN_OPEN_PERM` bit is added to the `event_mask` used by the `fanotify_mark` function<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token keyword\">static</span> <span class=\"token class-name\">uint64_t</span> event_mask <span class=\"token operator\">=</span>\n    <span class=\"token punctuation\">(</span>FAN_OPEN_PERM <span class=\"token operator\">|</span>\n     FAN_ACCESS <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File accessed */</span>\n     FAN_MODIFY <span class=\"token operator\">|</span>         <span class=\"token comment\">/* File modified */</span>\n     FAN_CLOSE_WRITE <span class=\"token operator\">|</span>    <span class=\"token comment\">/* Writtable file closed */</span>\n     FAN_CLOSE_NOWRITE <span class=\"token operator\">|</span>  <span class=\"token comment\">/* Unwrittable file closed */</span>\n     FAN_OPEN <span class=\"token operator\">|</span>           <span class=\"token comment\">/* File was opened */</span>\n     FAN_ONDIR <span class=\"token operator\">|</span>          <span class=\"token comment\">/* We want to be reported of events in the directory */</span>\n     FAN_EVENT_ON_CHILD<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">/* We want to be reported of events in files of the directory */</span></code></pre></div>\n<p>Once you add this, fanotify suspends the target operation until it receives a notification that allows or denies the operation through the file descriptor created by <code class=\"language-text\">fanotify_init</code>. (Apparently the default timeout is 5 seconds.)</p>\n<p>After that, when a filesystem event is received from fanotify, the code checks whether the target file is <code class=\"language-text\">/home/rana/eicar</code>, and only if that specific file was accessed does it set the <code class=\"language-text\">response</code> member of the <code class=\"language-text\">fanotify_response</code> structure to <code class=\"language-text\">FAN_DENY</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_response</span> response<span class=\"token punctuation\">;</span>\nresponse<span class=\"token punctuation\">.</span>fd <span class=\"token operator\">=</span> event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">strcmp</span><span class=\"token punctuation\">(</span><span class=\"token function\">get_file_path_from_fd</span><span class=\"token punctuation\">(</span>event<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">,</span>\n                                 path<span class=\"token punctuation\">,</span>\n                                 PATH_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                                 <span class=\"token string\">\"/home/rana/eicar\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    response<span class=\"token punctuation\">.</span>response <span class=\"token operator\">=</span> FAN_DENY<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">else</span>\n<span class=\"token punctuation\">{</span>\n    response<span class=\"token punctuation\">.</span>response <span class=\"token operator\">=</span> FAN_ALLOW<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">write</span><span class=\"token punctuation\">(</span>fanotify_fd<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>response<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>When you run this program, accesses are denied only when a file at the hard-coded path below is touched.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/b906adb75d4103ce5d0e57cc830818d2/03bcf/image-20241027224825657.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 63.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYUlEQVQ4y52SWXKDMBBEOYM3JAQCAWIzBlLJ/a/WmZaRXan4x/7oGlGIR8/0JNu2YV0XLMuCrvNomgZ934dn7z3qun5oGAfM2w3X+Yp5nsM93o9qRUlZlfKig7UWhS3A57IscblccDwecTqdgg6HA1zvMf6saAXctB55YaEzsyuD0hqJcw7zbUa3Q6N0pgM06ixQ1w8Yvn8wfa1w4r5se1S+l9qh9p2YqZA0bYNxGoPlylVwtUPd1MjzPDh7AM9nKJVCayWSKuc0TaF2hbNSSCqhcjatb58OSxuAEfQECkxpqVqgr5XQEVumU86OMEL5I5Ob/8DwoQq6g9VfIFsdxaGXhDlPiokSTsAr4BP8wiHdTDJDzs0Yc5c4yyS1CHsLOF2nEArnGGs8f+QwhsJW4y7GGfLC28C4NlxuBkRxfdgyV+FtIJ0tyy2AiqK4p7yvzUcztDYPG04gwzAme4TzCfAXcXFajUBi6rYAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/b906adb75d4103ce5d0e57cc830818d2/8ac56/image-20241027224825657.webp 240w,\n/static/b906adb75d4103ce5d0e57cc830818d2/d3be9/image-20241027224825657.webp 480w,\n/static/b906adb75d4103ce5d0e57cc830818d2/e46b2/image-20241027224825657.webp 960w,\n/static/b906adb75d4103ce5d0e57cc830818d2/f992d/image-20241027224825657.webp 1440w,\n/static/b906adb75d4103ce5d0e57cc830818d2/63e6a/image-20241027224825657.webp 1653w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/b906adb75d4103ce5d0e57cc830818d2/8ff5a/image-20241027224825657.png 240w,\n/static/b906adb75d4103ce5d0e57cc830818d2/e85cb/image-20241027224825657.png 480w,\n/static/b906adb75d4103ce5d0e57cc830818d2/d9199/image-20241027224825657.png 960w,\n/static/b906adb75d4103ce5d0e57cc830818d2/07a9c/image-20241027224825657.png 1440w,\n/static/b906adb75d4103ce5d0e57cc830818d2/03bcf/image-20241027224825657.png 1653w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/b906adb75d4103ce5d0e57cc830818d2/d9199/image-20241027224825657.png\"\n            alt=\"image-20241027224825657\"\n            title=\"image-20241027224825657\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<h2 id=\"reading-clamonacc\" style=\"position:relative;\"><a href=\"#reading-clamonacc\" aria-label=\"reading clamonacc permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reading clamonacc</h2>\n<p>Now that I have a rough understanding of how to use fanotify, I will take a closer look at the <code class=\"language-text\">clamonacc</code> code that ClamAV uses when On-Access scanning is enabled.</p>\n<h3 id=\"checking-the-implementation-of-the-clamonacc-main-function\" style=\"position:relative;\"><a href=\"#checking-the-implementation-of-the-clamonacc-main-function\" aria-label=\"checking the implementation of the clamonacc main function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Checking the implementation of the clamonacc main function</h3>\n<p>In ClamAV, On-Access scanning seems to be realized by two cooperating processes: <code class=\"language-text\">clamonacc</code> and <code class=\"language-text\">clamd</code>.</p>\n<p>Since <code class=\"language-text\">clamd</code> is the multithreaded daemon process that uses libclamav to perform virus scanning, I will start by looking at the <code class=\"language-text\">clamonacc</code> code to understand the behavior of On-Access scanning.</p>\n<h3 id=\"initialization\" style=\"position:relative;\"><a href=\"#initialization\" aria-label=\"initialization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Initialization</h3>\n<p>Inside the <code class=\"language-text\">clamonacc</code> main function, the first step is to initialize storage for <code class=\"language-text\">onas_context</code> by using the <code class=\"language-text\">onas_init_context</code> function.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span><span class=\"token function\">onas_init_context</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span>ctx <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token function\">cli_malloc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">NULL</span> <span class=\"token operator\">==</span> ctx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">memset</span><span class=\"token punctuation\">(</span>ctx<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> ctx<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Although <code class=\"language-text\">cli_malloc</code>, which is used here for memory allocation, is a ClamAV-specific function, it appears to be a simple wrapper that allocates memory with <code class=\"language-text\">malloc</code> using the size passed as its argument.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">CLI_MAX_ALLOCATION</span> <span class=\"token expression\"><span class=\"token punctuation\">(</span><span class=\"token number\">182</span> <span class=\"token operator\">*</span> <span class=\"token number\">1024</span> <span class=\"token operator\">*</span> <span class=\"token number\">1024</span><span class=\"token punctuation\">)</span></span></span>\n\n<span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">cli_malloc</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>alloc<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>size <span class=\"token operator\">||</span> size <span class=\"token operator\">></span> CLI_MAX_ALLOCATION<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">cli_errmsg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"cli_malloc(): Attempt to allocate %lu bytes. Please report to https://github.com/Cisco-Talos/clamav/issues\\n\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span>size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    alloc <span class=\"token operator\">=</span> <span class=\"token function\">malloc</span><span class=\"token punctuation\">(</span>size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>alloc<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">perror</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"malloc_problem\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">cli_errmsg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"cli_malloc(): Can't allocate memory (%lu bytes).\\n\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">long</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span>size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span>\n        <span class=\"token keyword\">return</span> alloc<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nThe `onas_context` structure allocated here contains a variety of information related to scanning<span class=\"token punctuation\">,</span> but in the current version it does not seem to be used that heavily<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>name<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>cmd<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>strarg<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">long</span> <span class=\"token keyword\">long</span> numarg<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> enabled<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> active<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> flags<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> idx<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token operator\">*</span>nextarg<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token operator\">*</span>next<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>filename<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* cmdline */</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token operator\">*</span>opts<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token operator\">*</span>clamdopts<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">int</span> printinfected<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> maxstream<span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">uint32_t</span> ddd_enabled<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">int</span> fan_fd<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint64_t</span> fan_mask<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint8_t</span> retry_on_error<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint8_t</span> retry_attempts<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint8_t</span> deny_on_error<span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">uint64_t</span> sizelimit<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint64_t</span> extinfo<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">int</span> scantype<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> isremote<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> session<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> timeout<span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">int64_t</span> portnum<span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">int32_t</span> maxthreads<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token keyword\">__attribute__</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>packed<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n### Getting command<span class=\"token operator\">-</span>line arguments\n\nThe next few lines parse the command<span class=\"token operator\">-</span>line arguments <span class=\"token keyword\">for</span> `clamonacc`<span class=\"token punctuation\">.</span>\n\nThe command<span class=\"token operator\">-</span>line arguments obtained here are stored in the `opts` member of the context<span class=\"token punctuation\">,</span> and the information parsed by the `optparse` function is stored in the `clamdopts` member<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token comment\">/* Parse out all our command line options */</span>\nopts <span class=\"token operator\">=</span> <span class=\"token function\">optparse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">NULL</span><span class=\"token punctuation\">,</span> argc<span class=\"token punctuation\">,</span> argv<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> OPT_CLAMONACC<span class=\"token punctuation\">,</span> OPT_CLAMSCAN<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>opts <span class=\"token operator\">==</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: can't parse command line options\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nctx<span class=\"token operator\">-></span>opts <span class=\"token operator\">=</span> opts<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">optget</span><span class=\"token punctuation\">(</span>opts<span class=\"token punctuation\">,</span> <span class=\"token string\">\"verbose\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>enabled<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    mprintf_verbose <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    logg_verbose    <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">/* And our config file options */</span>\nclamdopts <span class=\"token operator\">=</span> <span class=\"token function\">optparse</span><span class=\"token punctuation\">(</span><span class=\"token function\">optget</span><span class=\"token punctuation\">(</span>opts<span class=\"token punctuation\">,</span> <span class=\"token string\">\"config-file\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>strarg<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> OPT_CLAMD<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>clamdopts <span class=\"token operator\">==</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: can't parse clamd configuration file %s\\n\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">optget</span><span class=\"token punctuation\">(</span>opts<span class=\"token punctuation\">,</span> <span class=\"token string\">\"config-file\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>strarg<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">optfree</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">optstruct</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>opts<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nctx<span class=\"token operator\">-></span>clamdopts <span class=\"token operator\">=</span> clamdopts<span class=\"token punctuation\">;</span>\n\nBoth of these are pointers to `optstruct` structures and are managed as linked lists<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241025221022858</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241025221022858.</span>png<span class=\"token punctuation\">)</span>\n\n### Registering fanotify\n\nNext comes the startup check performed by the `startup_checks` function<span class=\"token punctuation\">.</span>\n\nIf this check returns any meaningful value<span class=\"token punctuation\">,</span> execution appears to jump to the `done` section and the process exits after cleanup<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token comment\">/* Make sure we're good to begin spinup */</span>\nret <span class=\"token operator\">=</span> <span class=\"token function\">startup_checks</span><span class=\"token punctuation\">(</span>ctx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ret<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ret <span class=\"token operator\">==</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span>CL_BREAK<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        ret <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">goto</span> done<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nInside the `startup_checks` function<span class=\"token punctuation\">,</span> fanotify is registered<span class=\"token punctuation\">.</span>\n\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">if</span> <span class=\"token expression\"><span class=\"token function\">defined</span><span class=\"token punctuation\">(</span>_GNU_SOURCE<span class=\"token punctuation\">)</span></span></span>\nctx<span class=\"token operator\">-></span>fan_fd <span class=\"token operator\">=</span> <span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span> O_LARGEFILE <span class=\"token operator\">|</span> O_RDONLY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">else</span></span>\nctx<span class=\"token operator\">-></span>fan_fd <span class=\"token operator\">=</span> <span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span> O_RDONLY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ctx<span class=\"token operator\">-></span>fan_fd <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: fanotify_init failed: %s\\n\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">cli_strerror</span><span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">,</span> faerr<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>faerr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>errno <span class=\"token operator\">==</span> EPERM<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: clamonacc must have elevated permissions ... exiting ...\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    ret <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">goto</span> done<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nRegistration with fanotify is performed by the `fanotify_init` function<span class=\"token punctuation\">.</span>\n\nWhen I debugged this in my local environment<span class=\"token punctuation\">,</span> I confirmed that the `fanotify_init` function was called with the arguments in `<span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span>FAN_CLASS_CONTENT <span class=\"token operator\">|</span> FAN_UNLIMITED_QUEUE <span class=\"token operator\">|</span> FAN_UNLIMITED_MARKS<span class=\"token punctuation\">,</span> O_LARGEFILE <span class=\"token operator\">|</span> O_RDONLY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>`<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241025225143323</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241025225143323.</span>png<span class=\"token punctuation\">)</span>\n\nThis function creates and initializes a fanotify group<span class=\"token punctuation\">.</span>\n\nAs its <span class=\"token keyword\">return</span> value<span class=\"token punctuation\">,</span> `fanotify_init` returns the file descriptor <span class=\"token keyword\">for</span> the event queue associated with the group it created<span class=\"token punctuation\">.</span>\n\nIn `clamonacc`<span class=\"token punctuation\">,</span> this <span class=\"token keyword\">return</span> value appears to be stored in the `fan_fd` member of the context<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">fanotify_init</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> Linux manual page<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//man7.org/linux/man-pages/man2/fanotify_init.2.html)</span>\n\nThe `flag` value passed as the first argument to `fanotify_init` includes the notification class configuration<span class=\"token punctuation\">.</span>\n\nIn `clamonacc`<span class=\"token punctuation\">,</span> it registers `FAN_CLASS_CONTENT`<span class=\"token punctuation\">,</span> which is generally used by AntiVirus software<span class=\"token punctuation\">.</span>\n\nThis class can receive both <span class=\"token string\">\"events that notify you when a file access has occurred\"</span> and <span class=\"token string\">\"events used to decide whether access to that file should be permitted.\"</span>\n\nIt also specifies `FAN_UNLIMITED_QUEUE` and `FAN_UNLIMITED_MARKS`<span class=\"token punctuation\">,</span> which remove the limits on the number of fanotify marks and queued events<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">fanotify</span><span class=\"token punctuation\">(</span><span class=\"token number\">7</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> Linux manual page<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//man7.org/linux/man-pages/man7/fanotify.7.html)</span>\n\nThe second argument also includes `O_LARGEFILE <span class=\"token operator\">|</span> O_RDONLY`<span class=\"token punctuation\">.</span>\n\n`O_LARGEFILE` supports monitoring files larger than <span class=\"token number\">2</span> GB<span class=\"token punctuation\">,</span> and `O_RDONLY` appears to configure read<span class=\"token operator\">-</span>only access<span class=\"token punctuation\">.</span>\n\nAfter calling `fanotify_init`<span class=\"token punctuation\">,</span> the monitoring targets are registered via the `fanotify_mark` function<span class=\"token punctuation\">.</span>\n\nIn `clamonacc`<span class=\"token punctuation\">,</span> there are several branches that call `fanotify_mark` depending on the `clamd` configuration<span class=\"token punctuation\">.</span> But when a mount point is specified with the `OnAccessMountPath` option<span class=\"token punctuation\">,</span> the following code in `fanotif<span class=\"token punctuation\">.</span>c`<span class=\"token punctuation\">,</span> called from `onas_setup_fanotif`<span class=\"token punctuation\">,</span> appears to run<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241101223410446</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241101223410446.</span>png<span class=\"token punctuation\">)</span>\n\nHere<span class=\"token punctuation\">,</span> `<span class=\"token function\">fanotify_mark</span><span class=\"token punctuation\">(</span>onas_fan_fd<span class=\"token punctuation\">,</span> FAN_MARK_ADD <span class=\"token operator\">|</span> FAN_MARK_MOUNT<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>fan_mask<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>fan_fd<span class=\"token punctuation\">,</span> pt<span class=\"token operator\">-></span>strarg<span class=\"token punctuation\">)</span>` is executed<span class=\"token punctuation\">,</span> and the path specified by `OnAccessMountPath` is passed in the `pt<span class=\"token operator\">-></span>strarg` argument<span class=\"token punctuation\">.</span>\n\nNote that ClamAV cannot use the `OnAccessMountPath` option together with `OnAccessPrevention`<span class=\"token punctuation\">,</span> which blocks file access with fanotify<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">></span> The OnAccessMountPath option uses a different fanotify api configuration which makes it incompatible with OnAccessIncludePath and the DDD System<span class=\"token punctuation\">.</span> Therefore<span class=\"token punctuation\">,</span> inotify watch<span class=\"token operator\">-</span>point limitations will not be a concern when using this option<span class=\"token punctuation\">.</span> Unfortunately<span class=\"token punctuation\">,</span> this also means that the following options cannot be used in conjunction with OnAccessMountPath<span class=\"token operator\">:</span>\n<span class=\"token operator\">></span>\n<span class=\"token operator\">></span> OnAccessExtraScanning <span class=\"token operator\">-</span> is built around catching inotify events<span class=\"token punctuation\">.</span>\n<span class=\"token operator\">></span> OnAccessExcludePath <span class=\"token operator\">-</span> is built upon the DDD System<span class=\"token punctuation\">.</span>\n<span class=\"token operator\">></span> OnAccessPrevention <span class=\"token operator\">-</span> would lock up the system <span class=\"token keyword\">if</span> <span class=\"token operator\">/</span> was selected <span class=\"token keyword\">for</span> OnAccessMountPath<span class=\"token punctuation\">.</span> If you need OnAccessPrevention<span class=\"token punctuation\">,</span> you should use OnAccessIncludePath instead of OnAccessMountPath<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>On<span class=\"token operator\">-</span>Access Scanning <span class=\"token operator\">-</span> ClamAV Documentation<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//docs.clamav.net/manual/OnAccess.html)</span>\n\nThat means <span class=\"token keyword\">if</span> you specify `OnAccessMountPath` rather than `OnAccessIncludePath`<span class=\"token punctuation\">,</span> access itself will not be blocked even <span class=\"token keyword\">if</span> a file is detected<span class=\"token punctuation\">.</span>\n\nIn fact<span class=\"token punctuation\">,</span> when you read the `clamonacc` source code<span class=\"token punctuation\">,</span> you can confirm that when `OnAccessMountPath` is enabled<span class=\"token punctuation\">,</span> the fanotify mask uses `FAN_OPEN` rather than `FAN_OPEN_PERM`<span class=\"token punctuation\">.</span>\n\nHowever<span class=\"token punctuation\">,</span> <span class=\"token keyword\">for</span> testing purposes<span class=\"token punctuation\">,</span> I modified the source code as shown below so that file access would still be blocked even when `OnAccessMountPath` was enabled<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241103155744015</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241103155744015.</span>png<span class=\"token punctuation\">)</span>\n\nOnce the processing in `onas_setup_fanotif` described above finishes<span class=\"token punctuation\">,</span> `onas_handle_signals` and `onas_start_eloop` are called<span class=\"token punctuation\">,</span> and monitoring <span class=\"token keyword\">for</span> On<span class=\"token operator\">-</span>Access scanning begins<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token comment\">/* Setup fanotify */</span>\n<span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span><span class=\"token function\">onas_setup_fanotif</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>ctx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">case</span> CL_SUCCESS<span class=\"token operator\">:</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">case</span> CL_BREAK<span class=\"token operator\">:</span>\n        ret <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">goto</span> done<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">case</span> CL_EARG<span class=\"token operator\">:</span>\n    <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n        <span class=\"token function\">mprintf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: can't setup fanotify\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        ret <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">goto</span> done<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n    \n<span class=\"token comment\">/* Setup signal handling */</span>\ng_ctx <span class=\"token operator\">=</span> ctx<span class=\"token punctuation\">;</span>\n<span class=\"token function\">onas_handle_signals</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*Clamonacc: beginning event loops\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">/*  Kick off event loop(s) */</span>\nret <span class=\"token operator\">=</span> <span class=\"token function\">onas_start_eloop</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>ctx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"setting-up-signal-handling\" style=\"position:relative;\"><a href=\"#setting-up-signal-handling\" aria-label=\"setting up signal handling permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up signal handling</h3>\n<p>The <code class=\"language-text\">onas_handle_signals</code> function sets up signal handling with the code below.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">onas_handle_signals</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">sigset_t</span> sigset<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">sigaction</span> act<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* ignore all signals except SIGUSR1 */</span>\n    <span class=\"token function\">sigfillset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGUSR1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGUSR2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">/* The behavior of a process is undefined after it ignores a\n\t * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGFPE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGILL<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGSEGV<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGINT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGTERM<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifdef</span> <span class=\"token expression\">SIGBUS</span></span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGBUS<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span>\n    <span class=\"token function\">pthread_sigmask</span><span class=\"token punctuation\">(</span>SIG_SETMASK<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">memset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>act<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">sigaction</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    act<span class=\"token punctuation\">.</span>sa_handler <span class=\"token operator\">=</span> onas_clamonacc_exit<span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigfillset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span><span class=\"token punctuation\">(</span>act<span class=\"token punctuation\">.</span>sa_mask<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaction</span><span class=\"token punctuation\">(</span>SIGUSR2<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>act<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaction</span><span class=\"token punctuation\">(</span>SIGTERM<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>act<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaction</span><span class=\"token punctuation\">(</span>SIGSEGV<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>act<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigaction</span><span class=\"token punctuation\">(</span>SIGINT<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>act<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nAfter initializing the signal set so that it includes all signals with the `sigfillset` function<span class=\"token punctuation\">,</span> the code removes some of those signals from the set with `sigdelset`<span class=\"token punctuation\">.</span>\n\nAfter that<span class=\"token punctuation\">,</span> it uses the newly prepared `sigaction` structure named `act` to associate signals such as `SIGTERM` with the `onas_clamonacc_exit` function<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token function\">sigfillset</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span> man page<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//nxmnpg.lemoda.net/ja/3/sigfillset)</span>\n\nWhen I actually debugged what happened after issuing `SIGTERM` with the `kill` command<span class=\"token punctuation\">,</span> I confirmed that `onas_clamonacc_exit` was called and the process terminated<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241101230336454</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241101230336454.</span>png<span class=\"token punctuation\">)</span>\n\n### Waiting <span class=\"token keyword\">for</span> scan events\n\nIf execution reaches this point<span class=\"token punctuation\">,</span> the `onas_start_eloop` function is finally called to trigger the event loop<span class=\"token punctuation\">.</span>\n\nInside that function<span class=\"token punctuation\">,</span> `onas_fan_eloop` is executed in turn<span class=\"token punctuation\">.</span>\n\nA partial implementation of that function is shown below<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token class-name\">time_t</span> start <span class=\"token operator\">=</span> <span class=\"token function\">time</span><span class=\"token punctuation\">(</span><span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">30</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>bread <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>fan_fd<span class=\"token punctuation\">,</span> buf<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>buf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token punctuation\">(</span>errno <span class=\"token operator\">==</span> EOVERFLOW <span class=\"token operator\">||</span> errno <span class=\"token operator\">==</span> EMFILE <span class=\"token operator\">||</span> errno <span class=\"token operator\">==</span> EACCES<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>errno<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n    <span class=\"token punctuation\">}</span>\n\n    fmd <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>buf<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAN_EVENT_OK</span><span class=\"token punctuation\">(</span>fmd<span class=\"token punctuation\">,</span> bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        \n        <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n\n        scan <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n\n        <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\nJust like in the sample code used earlier in this article<span class=\"token punctuation\">,</span> `fanotify_event_metadata` is read into `buf` from the file descriptor registered with fanotify<span class=\"token punctuation\">,</span> the `FAN_EVENT_OK` macro is used to validate the event<span class=\"token punctuation\">,</span> and then the `scan` flag is set to <span class=\"token number\">1.</span>\n\nAfter several additional checks<span class=\"token punctuation\">,</span> a variable of type `onas_scan_event` is initialized and populated<span class=\"token punctuation\">.</span>\n\nThe `onas_scan_event` structure stores information such as the file name obtained with the `readlink` function<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_scan_event</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>tcpaddr<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">int64_t</span> portnum<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>pathname<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> fan_fd<span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">if</span> <span class=\"token expression\"><span class=\"token function\">defined</span><span class=\"token punctuation\">(</span>HAVE_SYS_FANOTIFY_H<span class=\"token punctuation\">)</span></span></span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span> <span class=\"token operator\">*</span>fmd<span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span>\n    <span class=\"token class-name\">uint8_t</span> retry_attempts<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint64_t</span> sizelimit<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">int32_t</span> scantype<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">int64_t</span> maxstream<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">int64_t</span> timeout<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">uint8_t</span> bool_opts<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token function\">__attribute</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>packed<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>scan<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_scan_event</span> <span class=\"token operator\">*</span>event_data<span class=\"token punctuation\">;</span>\n\n    event_data <span class=\"token operator\">=</span> <span class=\"token function\">cli_calloc</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_scan_event</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    \n    <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n\n    <span class=\"token comment\">/* general mapping */</span>\n    <span class=\"token function\">onas_map_context_info_to_event_data</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>event_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    scan <span class=\"token operator\">?</span> event_data<span class=\"token operator\">-></span>bool_opts <span class=\"token operator\">|=</span> ONAS_SCTH_B_SCAN <span class=\"token operator\">:</span> scan<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* fanotify specific stuffs */</span>\n    event_data<span class=\"token operator\">-></span>bool_opts <span class=\"token operator\">|=</span> ONAS_SCTH_B_FANOTIFY<span class=\"token punctuation\">;</span>\n    event_data<span class=\"token operator\">-></span>fmd <span class=\"token operator\">=</span> <span class=\"token function\">cli_malloc</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    \n    <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n           \n    <span class=\"token function\">memcpy</span><span class=\"token punctuation\">(</span>event_data<span class=\"token operator\">-></span>fmd<span class=\"token punctuation\">,</span> fmd<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">fanotify_event_metadata</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    event_data<span class=\"token operator\">-></span>pathname <span class=\"token operator\">=</span> <span class=\"token function\">cli_strdup</span><span class=\"token punctuation\">(</span>fname<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    \n    <span class=\"token operator\">*</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span>\n\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*ClamFanotif: attempting to feed consumer queue\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* feed consumer queue */</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>CL_SUCCESS <span class=\"token operator\">!=</span> <span class=\"token function\">onas_queue_event</span><span class=\"token punctuation\">(</span>event_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fmd<span class=\"token operator\">-></span>fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>event_data<span class=\"token operator\">-></span>pathname<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>event_data<span class=\"token operator\">-></span>fmd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">free</span><span class=\"token punctuation\">(</span>event_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!ClamFanotif: error occurred while feeding consumer queue ... \\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>retry_on_error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            err_cnt<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>err_cnt <span class=\"token operator\">&lt;</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>retry_attempts<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ClamFanotif: ... recovering ...\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                fmd <span class=\"token operator\">=</span> <span class=\"token function\">FAN_EVENT_NEXT</span><span class=\"token punctuation\">(</span>fmd<span class=\"token punctuation\">,</span> bread<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The <code class=\"language-text\">event_data</code> variable created here, which is a value of type <code class=\"language-text\">onas_scan_event</code>, is ultimately passed to the <code class=\"language-text\">onas_queue_event</code> function.</p>\n<p>Inside this function, it first acquires a lock using the <code class=\"language-text\">pthread_mutex_t</code> variable <code class=\"language-text\">onas_queue_lock</code>, which is defined as a global variable.</p>\n<p>It then appends a node to the queue list managed around the global variable <code class=\"language-text\">g_onas_event_queue_tail</code> and writes the <code class=\"language-text\">event_data</code> received as an argument into that node.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token class-name\">cl_error_t</span> <span class=\"token function\">onas_queue_event</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_scan_event</span> <span class=\"token operator\">*</span>event_data<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_event_queue_node</span> <span class=\"token operator\">*</span>node <span class=\"token operator\">=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>CL_EMEM <span class=\"token operator\">==</span> <span class=\"token function\">onas_new_event_queue_node</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> CL_EMEM<span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">pthread_mutex_lock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_queue_lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    node<span class=\"token operator\">-></span>next                                                            <span class=\"token operator\">=</span> g_onas_event_queue_tail<span class=\"token punctuation\">;</span>\n    node<span class=\"token operator\">-></span>prev                                                            <span class=\"token operator\">=</span> g_onas_event_queue_tail<span class=\"token operator\">-></span>prev<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_event_queue_node</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>g_onas_event_queue_tail<span class=\"token operator\">-></span>prev<span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>next <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span>\n    g_onas_event_queue_tail<span class=\"token operator\">-></span>prev                                         <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span>\n\n    node<span class=\"token operator\">-></span>data <span class=\"token operator\">=</span> event_data<span class=\"token punctuation\">;</span>\n\n    g_onas_event_queue<span class=\"token punctuation\">.</span>size<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">pthread_cond_signal</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_scan_queue_empty_cond<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">pthread_mutex_unlock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_queue_lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> CL_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nSo this appears to be the point where data containing information about the scan target is added to the queue<span class=\"token punctuation\">.</span>\n\n### Monitoring the scan queue\n\nAlthough the order is a bit reversed in this explanation<span class=\"token punctuation\">,</span> the following code is executed in the `main` function of `clamonacc<span class=\"token punctuation\">.</span>c` before `onas_setup_fanotif` performs the fanotify registration<span class=\"token punctuation\">.</span>\n\n<span class=\"token comment\">/* Setup our event queue */</span>\nctx<span class=\"token operator\">-></span>maxthreads <span class=\"token operator\">=</span> <span class=\"token function\">optget</span><span class=\"token punctuation\">(</span>ctx<span class=\"token operator\">-></span>clamdopts<span class=\"token punctuation\">,</span> <span class=\"token string\">\"OnAccessMaxThreads\"</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-></span>numarg<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span><span class=\"token function\">onas_scan_queue_start</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>ctx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">case</span> CL_SUCCESS<span class=\"token operator\">:</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">case</span> CL_BREAK<span class=\"token operator\">:</span>\n    <span class=\"token keyword\">case</span> CL_EARG<span class=\"token operator\">:</span>\n    <span class=\"token keyword\">case</span> CL_ECREAT<span class=\"token operator\">:</span>\n    <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n        ret <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"!Clamonacc: can't setup event consumer queue\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">goto</span> done<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nThe `onas_scan_queue_start` function called here starts a new thread with the `pthread_create` function<span class=\"token punctuation\">.</span>\n\nAt that time<span class=\"token punctuation\">,</span> the `onas_scan_queue_th` function is set as the thread's `start_routine`<span class=\"token punctuation\">.</span>\n\n<span class=\"token class-name\">cl_error_t</span> <span class=\"token function\">onas_scan_queue_start</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n\n    <span class=\"token class-name\">pthread_attr_t</span> scan_queue_attr<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">int32_t</span> thread_started <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>ctx <span class=\"token operator\">||</span> <span class=\"token operator\">!</span><span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*ClamScanQueue: unable to start clamonacc. (bad context)\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> CL_EARG<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">pthread_attr_init</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>scan_queue_attr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> CL_BREAK<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">pthread_attr_setdetachstate</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>scan_queue_attr<span class=\"token punctuation\">,</span> PTHREAD_CREATE_JOINABLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    thread_started <span class=\"token operator\">=</span> <span class=\"token function\">pthread_create</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>scan_queue_pid<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>scan_queue_attr<span class=\"token punctuation\">,</span> onas_scan_queue_th<span class=\"token punctuation\">,</span> <span class=\"token operator\">*</span>ctx<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token number\">0</span> <span class=\"token operator\">!=</span> thread_started<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">/* Failed to create thread */</span>\n        <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*ClamScanQueue: Unable to start event consumer queue thread ... \\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> CL_ECREAT<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> CL_SUCCESS<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nAs shown above<span class=\"token punctuation\">,</span> inside the `onas_scan_queue_th` function<span class=\"token punctuation\">,</span> signal handling is configured with `sigfillset` and `sigdelset`<span class=\"token punctuation\">.</span>\n\nThis seems to overlap partially with the behavior of the `onas_handle_signals` function introduced earlier<span class=\"token punctuation\">.</span> But I <span class=\"token keyword\">do</span> not fully understand this area<span class=\"token punctuation\">,</span> so I <span class=\"token keyword\">do</span> not know why `sigfillset` is also used on the `onas_scan_queue_th` side<span class=\"token punctuation\">.</span>\n\nWhen I attached a debugger<span class=\"token punctuation\">,</span> the call order of `onas_handle_signals` and `onas_scan_queue_th` appeared inconsistent<span class=\"token punctuation\">,</span> and in some cases `onas_handle_signals` seemed to be called first<span class=\"token punctuation\">,</span> so I am not entirely sure whether they interfere with each other<span class=\"token punctuation\">.</span>\n\nIf I learn the reason <span class=\"token keyword\">for</span> this implementation later<span class=\"token punctuation\">,</span> I will add a note<span class=\"token punctuation\">.</span>\n\nAfter configuring signal handling<span class=\"token punctuation\">,</span> the `onas_init_event_queue` function initializes the `g_onas_event_queue` list of type `onas_event_queue` with size <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> and then the `onas_consume_event` function is executed in a loop<span class=\"token punctuation\">.</span>\n\n``` c\n<span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token function\">onas_scan_queue_th</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>arg<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n\n    <span class=\"token comment\">/* not a ton of use for context right now, but perhaps in the future we can pass in more options */</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span>ctx <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_context</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>arg<span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">sigset_t</span> sigset<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> ret<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* ignore all signals except SIGUSR2 */</span>\n    <span class=\"token function\">sigfillset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGUSR2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token comment\">/* The behavior of a process is undefined after it ignores a\n\t * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGFPE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGILL<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGSEGV<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGTERM<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGINT<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifdef</span> <span class=\"token expression\">SIGBUS</span></span>\n    <span class=\"token function\">sigdelset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>sigset<span class=\"token punctuation\">,</span> SIGBUS<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span>\n\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*ClamScanQueue: initializing event queue consumer ... (%d) threads in thread pool\\n\"</span><span class=\"token punctuation\">,</span> ctx<span class=\"token operator\">-></span>maxthreads<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">onas_init_event_queue</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    threadpool thpool <span class=\"token operator\">=</span> <span class=\"token function\">thpool_init</span><span class=\"token punctuation\">(</span>ctx<span class=\"token operator\">-></span>maxthreads<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    g_thpool          <span class=\"token operator\">=</span> thpool<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">/* loop w/ onas_consume_event until we die */</span>\n    <span class=\"token function\">pthread_cleanup_push</span><span class=\"token punctuation\">(</span>onas_scan_queue_exit<span class=\"token punctuation\">,</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">logg</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"*ClamScanQueue: waiting to consume events ...\\n\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">do</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">onas_consume_event</span><span class=\"token punctuation\">(</span>thpool<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">pthread_cleanup_pop</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nThe `onas_consume_event` function pops an element from the `g_onas_event_queue` queue and passes it to the thread pool together with the `onas_scan_worker` task by using the `thpool_add_work` function<span class=\"token punctuation\">.</span>\n\nReference<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>Pithikos<span class=\"token operator\">/</span>C<span class=\"token operator\">-</span>Thread<span class=\"token operator\">-</span>Pool<span class=\"token operator\">:</span> A minimal but powerful thread pool in ANSI C<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>https<span class=\"token operator\">:</span><span class=\"token comment\">//github.com/Pithikos/C-Thread-Pool/tree/master)</span>\n\n``` c\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span> <span class=\"token function\">onas_queue_is_b_empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>g_onas_event_queue<span class=\"token punctuation\">.</span>head<span class=\"token operator\">-></span>next <span class=\"token operator\">==</span> g_onas_event_queue<span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n\n<span class=\"token keyword\">static</span> <span class=\"token keyword\">int</span> <span class=\"token function\">onas_consume_event</span><span class=\"token punctuation\">(</span>threadpool thpool<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token function\">pthread_mutex_lock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_queue_lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">onas_queue_is_b_empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token function\">pthread_cond_wait</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_scan_queue_empty_cond<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>onas_queue_lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">onas_event_queue_node</span> <span class=\"token operator\">*</span>popped_node <span class=\"token operator\">=</span> g_onas_event_queue_head<span class=\"token operator\">-></span>next<span class=\"token punctuation\">;</span>\n    g_onas_event_queue_head<span class=\"token operator\">-></span>next             <span class=\"token operator\">=</span> g_onas_event_queue_head<span class=\"token operator\">-></span>next<span class=\"token operator\">-></span>next<span class=\"token punctuation\">;</span>\n    g_onas_event_queue_head<span class=\"token operator\">-></span>next<span class=\"token operator\">-></span>prev       <span class=\"token operator\">=</span> g_onas_event_queue_head<span class=\"token punctuation\">;</span>\n    g_onas_event_queue<span class=\"token punctuation\">.</span>size<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">pthread_mutex_unlock</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>onas_queue_lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">thpool_add_work</span><span class=\"token punctuation\">(</span>thpool<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>onas_scan_worker<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">)</span>popped_node<span class=\"token operator\">-></span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">onas_destroy_event_queue_node</span><span class=\"token punctuation\">(</span>popped_node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nThe `onas_scan_worker` function performs the scan job after several conditional branches<span class=\"token punctuation\">.</span>\n\nIn the environment I am using <span class=\"token keyword\">for</span> testing this time<span class=\"token punctuation\">,</span> it passes the event information retrieved from the queue to the `onas_scan_thread_handle_file` function<span class=\"token punctuation\">.</span>\n\n<span class=\"token operator\">!</span><span class=\"token punctuation\">[</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241102181444683</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">/</span><span class=\"token keyword\">static</span><span class=\"token operator\">/</span>media<span class=\"token operator\">/</span><span class=\"token number\">2024</span><span class=\"token operator\">-</span><span class=\"token number\">10</span><span class=\"token operator\">-</span><span class=\"token number\">23</span><span class=\"token operator\">-</span>clamav<span class=\"token operator\">-</span>onaccess<span class=\"token operator\">-</span>scanning<span class=\"token operator\">/</span>image<span class=\"token operator\">-</span><span class=\"token number\">20241102181444683.</span>png<span class=\"token punctuation\">)</span>\n\nAfter doing some simple checks and obtaining file information<span class=\"token punctuation\">,</span> the `onas_scan_thread_handle_file` function passes the initialized `infected` variable and related values to the `onas_scan_thread_scanfile` function<span class=\"token punctuation\">.</span>\n\n``` c\nret <span class=\"token operator\">=</span> <span class=\"token function\">onas_scan_thread_scanfile</span><span class=\"token punctuation\">(</span>event_data<span class=\"token punctuation\">,</span> curr<span class=\"token operator\">-></span>fts_path<span class=\"token punctuation\">,</span> sb<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>infected<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>err<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>ret_code<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The <code class=\"language-text\">onas_scan_thread_scanfile</code> function then calls <code class=\"language-text\">onas_scan</code> -> <code class=\"language-text\">onas_scan_safe</code> -> <code class=\"language-text\">onas_client_scan</code>, and eventually executes the <code class=\"language-text\">onas_dsresult</code> function, which issues the scan request to <code class=\"language-text\">clamd</code> and obtains the scan result.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token function\">onas_scan</span><span class=\"token punctuation\">(</span>event_data<span class=\"token punctuation\">,</span> fname<span class=\"token punctuation\">,</span> sb<span class=\"token punctuation\">,</span> infected<span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">,</span> ret_code<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n↓\n    \n<span class=\"token function\">onas_scan_safe</span><span class=\"token punctuation\">(</span>event_data<span class=\"token punctuation\">,</span> fname<span class=\"token punctuation\">,</span> sb<span class=\"token punctuation\">,</span> infected<span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">,</span> ret_code<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n↓\n    \n<span class=\"token function\">onas_client_scan</span><span class=\"token punctuation\">(</span>event_data<span class=\"token operator\">-></span>tcpaddr<span class=\"token punctuation\">,</span> event_data<span class=\"token operator\">-></span>portnum<span class=\"token punctuation\">,</span> event_data<span class=\"token operator\">-></span>scantype<span class=\"token punctuation\">,</span> event_data<span class=\"token operator\">-></span>maxstream<span class=\"token punctuation\">,</span>fname<span class=\"token punctuation\">,</span> fd<span class=\"token punctuation\">,</span> event_data<span class=\"token operator\">-></span>timeout<span class=\"token punctuation\">,</span> sb<span class=\"token punctuation\">,</span> infected<span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">,</span> ret_code<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n↓\n    \n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>ret <span class=\"token operator\">=</span> <span class=\"token function\">onas_dsresult</span><span class=\"token punctuation\">(</span>curl<span class=\"token punctuation\">,</span> scantype<span class=\"token punctuation\">,</span> maxstream<span class=\"token punctuation\">,</span> fname<span class=\"token punctuation\">,</span> fd<span class=\"token punctuation\">,</span> timeout<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>ret<span class=\"token punctuation\">,</span> err<span class=\"token punctuation\">,</span> ret_code<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">>=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token operator\">*</span>infected <span class=\"token operator\">=</span> ret<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Inside the <code class=\"language-text\">onas_scan_thread_scanfile</code> function, the final decision about whether the target file should be accessible is made based on the scan result received from <code class=\"language-text\">clamd</code>.</p>\n<p>If the scan determines that the target file is malware, the following code sets the <code class=\"language-text\">response</code> member of the <code class=\"language-text\">fanotify_response</code> structure to <code class=\"language-text\">FAN_DENY</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>b_fanotify<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>err <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">*</span>ret_code <span class=\"token operator\">&amp;&amp;</span> b_deny_on_error<span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token operator\">*</span>infected<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        res<span class=\"token punctuation\">.</span>response <span class=\"token operator\">=</span> FAN_DENY<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>With that, if the target file is detected, fanotify blocks access to the file.</p>\n<p>By the way, if the fanotify access mask is left as <code class=\"language-text\">FAN_OPEN_PERM</code>, I cannot make much progress when debugging fanotify itself, so this time I modified the code to use print-based debugging instead.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 690px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/8e2232e4c6dc99bf90fcfc9544d5b68c/1e043/image-20241103160512144.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 22.499999999999996%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABDElEQVQY001Q2WrDMBD0V5Tm0GHdkWwJu02wTQmlJD2glDw19P8/ZLqO+9CHYZjRatidKhiP6CK6XUFuD3DdAJcfYPMeut2j9glM1GDbLRhj4DM4XyDEwuQxNmuJivPZFKilhKHwpsnIfY9UCtwuwjqLkBp47+FigiXW5BljoaSA1vVtzgcDxe9QxSQRnACjUCk4fQzYny84nL/x9HFFeb4gn37Qna7oj5+IwyvK9IZ2JB5OKOMZifRuekc6fqFSloIknUPrKiWhjULoRjp5hKMKNLFqB5iG6sjEpENZ3n1ZYMhXeYJ7fEHltUcfe1rdgtPZglMfmzV1toBvV4Q/ffNXC29W/0BzM6/v8QtUo5MFLOuf+AAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/8e2232e4c6dc99bf90fcfc9544d5b68c/8ac56/image-20241103160512144.webp 240w,\n/static/8e2232e4c6dc99bf90fcfc9544d5b68c/d3be9/image-20241103160512144.webp 480w,\n/static/8e2232e4c6dc99bf90fcfc9544d5b68c/8efd0/image-20241103160512144.webp 690w\"\n              sizes=\"(max-width: 690px) 100vw, 690px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/8e2232e4c6dc99bf90fcfc9544d5b68c/8ff5a/image-20241103160512144.png 240w,\n/static/8e2232e4c6dc99bf90fcfc9544d5b68c/e85cb/image-20241103160512144.png 480w,\n/static/8e2232e4c6dc99bf90fcfc9544d5b68c/1e043/image-20241103160512144.png 690w\"\n            sizes=\"(max-width: 690px) 100vw, 690px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/8e2232e4c6dc99bf90fcfc9544d5b68c/1e043/image-20241103160512144.png\"\n            alt=\"image-20241103160512144\"\n            title=\"image-20241103160512144\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>When I actually tested detection of Eicar with On-Access scanning in my test environment, the code above executed as shown below, and I confirmed that access was denied via <code class=\"language-text\">FAN_DENY</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4af6bf60fbc6e76f69c7160ece4041c4/2130b/image-20241103154210665.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 11.666666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAd0lEQVQI1zXMWw7CIBSE4e6hfelFCwKHAxRqYtz/0n4rxocvk0wyM+RSaGej1tqllAgS0KQYY/DB905EkChYa5GstPeT43VS20E5MiknnHMMEgMh/A6+47+oEecdxhrmeWYcR6Zp6rntN3wRHiqo7uz3hXXdLgsfNyI47Ay6DKkAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/4af6bf60fbc6e76f69c7160ece4041c4/8ac56/image-20241103154210665.webp 240w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/d3be9/image-20241103154210665.webp 480w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/e46b2/image-20241103154210665.webp 960w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/7bb49/image-20241103154210665.webp 1271w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/4af6bf60fbc6e76f69c7160ece4041c4/8ff5a/image-20241103154210665.png 240w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/e85cb/image-20241103154210665.png 480w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/d9199/image-20241103154210665.png 960w,\n/static/4af6bf60fbc6e76f69c7160ece4041c4/2130b/image-20241103154210665.png 1271w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/4af6bf60fbc6e76f69c7160ece4041c4/d9199/image-20241103154210665.png\"\n            alt=\"image-20241103154210665\"\n            title=\"image-20241103154210665\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>Using ClamAV, an open-source AntiVirus product for Linux, as a reference, I summarized how file access control and On-Access scanning are implemented with fanotify.</p>","fields":{"slug":"/clamav-onaccess-scanning-en","tagSlugs":["/tag/clam-av/","/tag/malware/","/tag/linux/","/tag/english/"]},"frontmatter":{"date":"2024-11-03","description":"This article briefly explains fanotify, the kernel framework used for real-time file scanning (On-Access scanning) by AntiVirus software for Linux.","tags":["ClamAV","Malware","Linux","English"],"title":"ClamAV On-Access Scanning with fanotify - Learning AntiVirus on Linux Through OSS -","socialImage":{"publicURL":"/static/27ba833b286c6b09e628e3c23a921a74/clamav-onaccess-scanning.png"}}}},"pageContext":{"slug":"/clamav-onaccess-scanning-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}