Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden systemd services for freshclam and clamd #859

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
57 changes: 57 additions & 0 deletions clamd/clamav-daemon.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,68 @@ ConditionPathExistsGlob=@DATADIR@/main.{c[vl]d,inc}
ConditionPathExistsGlob=@DATADIR@/daily.{c[vl]d,inc}

[Service]
Type=simple
# WARNING: Must match clamd.conf directive
User=clamav
Group=clamav
;DynamicUser=yes
;ExecStartPre=/usr/bin/install --owner=root --group=root --mode=640 --directory /var/local/quarantine
ExecStart=@prefix@/sbin/clamd --foreground=true
# Reload the database
ExecReload=/bin/kill -USR2 $MAINPID
TimeoutStartSec=420
LogsDirectory=clamav
ConfigurationDirectory=clamav
RuntimeDirectory=clamav

#============================#
# Security Hardening Options #
#============================#
NoNewPrivileges=yes
;PrivateUsers=no

# Remove `ProtectSystem`, `ProtectHome`, and `ReadWritePaths`
# if you want ClamAV to be able to quarantine (`--move`) infected files.
ProtectSystem=strict
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=/var/local/quarantine

NoExecPaths=/
eternaltyro marked this conversation as resolved.
Show resolved Hide resolved
# WARNING: To execute targets of `VirusEvent` and `VirusAction` directives
# in the configuration, whitelist them in ExecPaths.
;ExecPaths=@prefix@/sbin/clamd /usr/local/bin/send_sms /usr/local/bin/my_infected_message_handler
ExecPaths=@prefix@/sbin/clamd @CMAKE_INSTALL_FULL_LIBDIR@ /bin/kill /usr/bin/install

ProtectClock=yes
ProtectHostname=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes

PrivateNetwork=yes
IPAddressDeny=any
RestrictAddressFamilies=none

# ProtectProc is only effective if:
# (1) Service is a system service and not a user service.
# (2) CAP_SYS_PTRACE is restricted and
# (3) Service user is non-root.
ProtectProc=invisible
ProcSubset=pid

CapabilityBoundingSet=CAP_CHOWN CAP_SETGID CAP_SETUID CAP_DAC_OVERRIDE CAP_MKNOD
RestrictNamespaces=yes
SystemCallFilter=~@clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @resources @swap

[Install]
WantedBy=multi-user.target
Also=clamav-daemon.socket
Alias=clamd.service
59 changes: 57 additions & 2 deletions clamonacc/clamav-clamonacc.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,64 @@ After=clamav-daemon.service syslog.target network.target

[Service]
Type=simple
# WARNING: Must match clamd.conf directive
User=root
ExecStartPre=/bin/bash -c "while [ ! -S /run/clamav/clamd.ctl ]; do sleep 1; done"
ExecStart=@prefix@/sbin/clamonacc -F --log=/var/log/clamav/clamonacc.log --move=/root/quarantine
Group=root
;DynamicUser=yes
ExecStartPre=/usr/bin/install --owner=root --group=root --mode=640 --directory /var/local/quarantine
ExecStart=@prefix@/sbin/clamonacc --foreground --log=/var/log/clamav/clamonacc.log --move=/var/local/quarantine --ping 120 --wait
ExecReload=/bin/kill -SIGHUP $MAINPID
ExecStop=/bin/kill -SIGTERM $MAINPID
;LogsDirectory=clamav
ConfigurationDirectory=clamav
;RuntimeDirectory=clamav

#============================#
# Security Hardening Options #
#============================#
NoNewPrivileges=yes
;PrivateUsers=no

# Remove `ProtectSystem`, `ProtectHome`, and `ReadWritePaths` if you
# want ClamAV to be able to quarantine or remove infected files.
ProtectSystem=strict
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=/var/local/quarantine /var/log/clamav

NoExecPaths=/
# WARNING: To execute targets of `VirusEvent` and `VirusAction` directives
# in the cofiguration, whitelist them in ExecPaths.
ExecPaths=@prefix@/sbin/clamonacc @CMAKE_INSTALL_FULL_LIBDIR@ /bin/kill /usr/bin/install

ProtectClock=yes
ProtectHostname=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes

PrivateNetwork=yes
IPAddressDeny=any
RestrictAddressFamilies=none

# ProtectProc is only effective if:
# (1) Service is a system service and not a user service.
# (2) CAP_SYS_PTRACE is restricted and
# (3) Service user is non-root.
ProtectProc=invisible
ProcSubset=pid

CapabilityBoundingset=CAP_CHOWN CAP_SETGID CAP_SETUID CAP_DAC_OVERRIDE CAP_MKNOD
RestrictNamespaces=yes
SystemCallFilter=~@clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @resources @swap

[Install]
WantedBy=multi-user.target
Alias=clamonacc.service
3 changes: 3 additions & 0 deletions etc/clamav-milter.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ Example
# Note #2: the process is invoked in the context of clamav-milter
# Note #3: clamav-milter will wait for the process to exit. Be quick or fork to
# avoid unnecessary delays in email delivery
# Note #4: When using systemd to manage ClamAv daemon, ensure that the full path to
# the VirusAction target binary / executable is listed in ExecPaths in the service
# file clamav-daemon.service in order for the process to be able to execute it.
# Default: disabled
#VirusAction /usr/local/bin/my_infected_message_handler

Expand Down
12 changes: 12 additions & 0 deletions etc/freshclam.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,27 @@ DatabaseMirror database.clamav.net

# Run command after successful database update.
# Use EXIT_1 to return 1 after successful database update.
# Note: When using systemd to manage FreshClam service, append the
# full path to the OnUpdateExecute target command to `ExecPaths` in the
# service file clamav-freshclam.service in order for the process to
# be able to execute it.
# Default: disabled
#OnUpdateExecute command

# Run command when database update process fails.
# Note: When using systemd to manage FreshClam service, append the
# full path to the OnErrorExecute target command to `ExecPaths` in the
# service file clamav-freshclam.service in order for the process to
# be able to execute it.
# Default: disabled
#OnErrorExecute command

# Run command when freshclam reports outdated version.
# In the command string %v will be replaced by the new version number.
# Note: When using systemd to manage FreshClam service, append the
# full path to the OnOutdatedExecute target command to `ExecPaths`
# in the service file clamav-freshclam.service in order for the process to
# be able to execute it.
# Default: disabled
#OnOutdatedExecute command

Expand Down
49 changes: 49 additions & 0 deletions freshclam/clamav-freshclam-once.service.in
Original file line number Diff line number Diff line change
@@ -1,12 +1,61 @@
[Unit]
Description=Update ClamAV virus database once
Documentation=man:freshclam(1) man:freshclam.conf(5) https://docs.clamav.net/
;ConditionPathExists=!/etc/cron.d/clamav-freshclam
Wants=network-online.target
After=network-online.target
Conflicts=clamav-freshclam.service

[Service]
Type=oneshot
# WARNING: Must match clamd.conf directive
User=clamav
Group=clamav
;DynamicUser=yes
ExecStart=@prefix@/bin/freshclam
LogsDirectory=clamav
ConfigurationDirectory=clamav
RuntimeDirectory=clamav

#============================#
# Security Hardening Options #
#============================#
NoNewPrivileges=yes
;PrivateUsers=no

ProtectSystem=full
ProtectHome=tmpfs
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=@DATADIR@

NoExecPaths=/
# WARNING: To execute targets of `OnUpdateExecute`, `OnErrorExecute` and `OnOutdatedExecute`
# directives in freshclam.conf, whitelist them in ExecPaths.
;ExecPaths=@prefix@/sbin/freshclam /usr/local/bin/OnOutdated.sh /usr/local/bin/OnErrorExecute.sh
ExecPaths=@prefix@/bin/freshclam

ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes

PrivateNetwork=no
IPAddressAllow=any
RestrictAddressFamilies=AF_INET AF_INET6

ProtectProc=noaccess
ProcSubset=pid

CapabilityBoundingSet=CAP_CHOWN CAP_SETGID CAP_SETUID CAP_DAC_OVERRIDE CAP_MKNOD
RestrictNamespaces=yes
SystemCallFilter=~@clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @resources @swap

[Install]
WantedBy=multi-user.target
49 changes: 49 additions & 0 deletions freshclam/clamav-freshclam.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,56 @@ Wants=network-online.target
After=network-online.target

[Service]
Type=simple
# WARNING: Must match clamd.conf directive
User=clamav
Group=clamav
;DynamicUser=yes
ExecStart=@prefix@/bin/freshclam -d --foreground=true
LogsDirectory=clamav
ConfigurationDirectory=clamav
RuntimeDirectory=clamav

#============================#
# Security Hardening Options #
#============================#
NoNewPrivileges=yes
;PrivateUsers=no

ProtectSystem=full
ProtectHome=tmpfs
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=@DATADIR@

NoExecPaths=/
# WARNING: To execute targets of `OnUpdateExecute`, `OnErrorExecute` and `OnOutdatedExecute`
# directives in freshclam.conf, whitelist them in ExecPaths.
;ExecPaths=@prefix@/sbin/freshclam /usr/local/bin/OnOutdated.sh /usr/local/bin/OnErrorExecute.sh
ExecPaths=@prefix@/bin/freshclam

ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
eternaltyro marked this conversation as resolved.
Show resolved Hide resolved
RestrictSUIDSGID=yes
SystemCallArchitectures=native
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes

PrivateNetwork=no
IPAddressAllow=any
RestrictAddressFamilies=AF_INET AF_INET6

ProtectProc=noaccess
ProcSubset=pid

CapabilityBoundingSet=CAP_CHOWN CAP_SETGID CAP_SETUID CAP_DAC_OVERRIDE CAP_MKNOD
RestrictNamespaces=yes
SystemCallFilter=~@clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @resources @swap

[Install]
WantedBy=multi-user.target
Alias=freshclam.service