This page has been machine-translated from the original page.
In 2024, I wanted to thoroughly read the source code of a larger product, and I decided to work with AntiVirus software, which I’m most interested in.
However, unfortunately, there are almost no AntiVirus Software products whose source code is publicly available.
Among them, ClamAV is almost the only AntiVirus Software that is developed as open source, primarily targeting mail gateways.
Although limited to Linux environments, ClamAV also has OnAccessScan (real-time scanning) functionality using fanotify, which many recent Linux AntiVirus products utilize, making it a very useful reference product. (ClamAV can also be used as an on-demand scanner on Windows systems.)
This time, as a starting point for understanding ClamAV’s source code, I’ve summarized the build and setup procedures for ClamAV 1.2.0.
Table of Contents
Prerequisites
Build & Install
I used the following commands to install ClamAV on Ubuntu 20.04.
# Run with root user in Ubuntu 20.04
apt-get update && apt-get install -y gcc make pkg-config python3 python3-pip python3-pytest valgrind cmake check libbz2-dev libcurl4-openssl-dev libjson-c-dev libmilter-dev libncurses5-dev libpcre2-dev libssl-dev libxml2-dev zlib1g-dev cargo rustc -y
# Install rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build and install
git clone https://github.com/Cisco-Talos/clamav.git
cd clamav && mkdir -p build && cd build
cmake ..
cmake --build . --target install
# Check install version
clamav-config --versionReference: Unix from source (v0.104+) - ClamAV Documentation
The CMakeLists.txt file in the root directory defines the build configuration for managing the build process with CMake.
For ClamAV 1.2.0, it’s approximately 1300 lines, but by skimming through it, you can get a rough overview of which files are used for the build.
Reference: clamav/CMakeLists.txt at clamav-1.2.0 · Cisco-Talos/clamav
In the following section, you can see that the cmake directory directly under the root is set as CMAKE_MODULE_PATH, and version information is included.
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
include(Version)
set(PACKAGE_NAME "${PROJECT_NAME}")
set(PACKAGE_VERSION "${PROJECT_VERSION}")
set(PACKAGE_STRING "${PROJECT_NAME} ${PROJECT_VERSION}${VERSION_SUFFIX}")
set(PACKAGE_BUGREPORT "https://github.com/Cisco-Talos/clamav/issues")
set(PACKAGE_URL "https://www.clamav.net/")
HexVersion(PACKAGE_VERSION_NUM ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR} ${PROJECT_VERSION_PATCH})Version.cmake defines two functions: HexVersion and NumberToHex.
As their names suggest, they seem to be used to convert version information values into hexadecimal strings.
Reference: clamav/cmake/Version.cmake at clamav-1.2.0 · Cisco-Talos/clamav
In the following section, it identifies whether the build target platform is Linux, Unix, or macOS.
For Linux, the C_LINUX flag is set.
# Define C_LINUX and C_BSD because CMake only defines UNIX, APPLE, WIN32, MSVC
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(C_LINUX 1)
elseif(APPLE OR CMAKE_SYSTEM_NAME MATCHES "BSD")
set(C_BSD 1)
endif()Setup
After installation, create the configuration files by copying the template configuration files.
The default locations for ClamAV configuration files are as follows:
- freshclam configuration:
/usr/local/etc/freshclam.conf.sample - clamd configuration:
/usr/local/etc/clamd.conf.sample
Since these are sample files, copy them as follows to use them as configuration files:
cp /usr/local/etc/freshclam.conf.sample /usr/local/etc/freshclam.conf
cp /usr/local/etc/clamd.conf.sample /usr/local/etc/clamd.confInstalled Modules
When you build and install ClamAV from source, the following files will be installed.
Main executables include:
- clamscan: On-demand scanner
- clamdscan: On-demand scanner client for clamd daemon
- clamd: ClamAV daemon
- freshclam: Signature database update tool
- clamconf: Configuration check tool
- clamdtop: clamd monitoring tool
And the following libraries are also installed:
- libclamav.so: ClamAV core library
- libfreshclam.so: Signature update library
Reference: Usage - ClamAV Documentation
Create Service User Account
ClamAV’s daemon and related services run under the clamav user and clamav group by default.
Create the clamav user account with the following command:
groupadd clamav
useradd -g clamav -s /bin/false -c "Clam Antivirus" clamavAlso, set the appropriate permissions for the directories used by ClamAV:
mkdir -p /usr/local/var/lib/clamav
chown -R clamav:clamav /usr/local/var/lib/clamav
mkdir -p /usr/local/var/log/clamav
chown -R clamav:clamav /usr/local/var/log/clamavCreate Configuration Files
Edit freshclam.conf
freshclam is a tool that automatically downloads the latest virus signature database.
Edit the configuration file as follows:
vi /usr/local/etc/freshclam.confKey configuration items:
# Comment out Example (required to use this configuration file)
# Example
# Database directory (default: /usr/local/var/lib/clamav)
DatabaseDirectory /usr/local/var/lib/clamav
# Update log file
UpdateLogFile /usr/local/var/log/clamav/freshclam.log
# Log file size limit
LogFileMaxSize 2M
# Log timestamp
LogTime yes
# syslog facility
LogSyslog no
# Run as this user
DatabaseOwner clamav
# Database mirror (default: database.clamav.net)
DatabaseMirror database.clamav.netAfter editing, run freshclam to download the signature database:
freshclamIf the update is successful, you should see output like:
ClamAV update process started at Sun Jan 28 10:00:00 2024
daily.cvd database is up-to-date (version: 27120, sigs: 2050127, f-level: 90, builder: raynman)
main.cvd database is up-to-date (version: 62, sigs: 6647427, f-level: 90, builder: sigmgr)
bytecode.cvd database is up-to-date (version: 334, sigs: 91, f-level: 90, builder: anvilleg)Edit clamd.conf
clamd is the ClamAV daemon that provides the scanning service.
Edit the configuration file as follows:
vi /usr/local/etc/clamd.confKey configuration items:
# Comment out Example (required to use this configuration file)
# Example
# Log file
LogFile /usr/local/var/log/clamav/clamd.log
# Log timestamp
LogTime yes
# Log file size limit
LogFileMaxSize 2M
# Run as this user
User clamav
# Unix socket path
LocalSocket /usr/local/var/run/clamav/clamd.sock
# Fix stale socket issues
FixStaleSocket yes
# TCP socket settings (if you want to use TCP instead of Unix socket)
# TCPSocket 3310
# TCPAddr 127.0.0.1
# Maximum number of threads for scanning
MaxThreads 12
# Maximum queue length
MaxQueue 100
# Idle timeout
IdleTimeout 30
# Exclude certain paths from scanning (use with OnAccessScan)
ExcludePath ^/proc/
ExcludePath ^/sys/
# OnAccessScan settings
OnAccessMountPath /home
OnAccessIncludePath /home
OnAccessExcludePath /home/clamav
OnAccessPrevention no
OnAccessExtraScanning yesCreate the necessary directory for the Unix socket:
mkdir -p /usr/local/var/run/clamav
chown -R clamav:clamav /usr/local/var/run/clamavEnable Debug and Systemd and Rebuild
To enable debugging and systemd support, rebuild ClamAV with additional options.
cd /path/to/clamav/build
cmake .. -D CMAKE_BUILD_TYPE=Debug -D ENABLE_SYSTEMD=ON
cmake --build . --target installThe Debug build type includes debugging symbols and disables optimization, making it easier to debug.
With systemd support enabled, you can register clamd and freshclam as systemd services.
Suppress Build Warnings
If you encounter build warnings, you can suppress specific warnings by adding flags to CMakeLists.txt.
For example, to suppress deprecation warnings:
add_compile_options(-Wno-deprecated-declarations)Configure Detection Notifications
When ClamAV detects malware, you can configure it to execute a specified script or send notifications.
Configure in clamd.conf:
# Command to execute when a virus is detected
VirusEvent /usr/local/bin/virus_alert.sh %v %f%v: Virus name%f: Infected file path
Example notification script:
#!/bin/bash
VIRUS=$1
FILE=$2
DATE=$(date)
echo "$DATE - Virus detected: $VIRUS in file $FILE" >> /var/log/clamav/virus_detected.log
# Add notification logic here (email, Slack, etc.)Make the script executable:
chmod +x /usr/local/bin/virus_alert.shSummary
In this article, I summarized the steps to build ClamAV 1.2.0 from source code and set up OnAccessScan.
Key points covered:
- Installing dependencies and building ClamAV from source
- Creating and configuring freshclam.conf and clamd.conf
- Creating service user accounts and setting directory permissions
- Enabling debug mode and systemd support
- Configuring detection notifications
ClamAV is a valuable resource for learning about AntiVirus implementation, especially the fanotify-based OnAccessScan feature on Linux.
In future articles, I plan to dive deeper into ClamAV’s source code to understand its internal architecture and scanning mechanisms.