RHEL-9.9 ERRATUM

Support for included files in /etc/aide.d/
Resolves: RHEL-178122
Increase default values for num_workers
Resolves: RHEL-178123
Add pre-configured systemd timer for aide check
Resolves: RHEL-178121
This commit is contained in:
Patrik Koncity 2026-05-26 11:33:39 +02:00
parent 64a9adb85d
commit 43cdcea6e5
6 changed files with 144 additions and 20 deletions

View File

@ -20,21 +20,28 @@
compared with the AIDE database. Prior to running a check manually,
ensure that the AIDE binary and database have not been modified
without your knowledge.
Caution!
With the default setup, an AIDE check is not run periodically as a
cron job. It cannot be guaranteed that the AIDE binaries, config
file and database are intact. It is not recommended that you run
automated AIDE checks without verifying AIDE yourself frequently.
In addition to that, AIDE does not implement any password or
encryption protection for its own files.
It is up to you how to put a file integrity checker to good effect
and how to set up automated checks if you think it adds a level of
safety (e.g. detecting failed/incomplete compromises or unauthorized
modification of special files). On a compromised system, the
intruder could disable the automated check. Or he could replace the
AIDE binary, config file and database easily when they are not
located on read-only media.
6) To schedule daily integrity checks, enable the systemd timer:
systemctl enable --now aide-check.timer
View results with: journalctl -u aide-check
Check timer status with: systemctl status aide-check.timer
The timer runs daily with low CPU/IO priority to minimize impact
on production workloads. It is disabled by default — only enable
it after initializing the database (steps 2-4).
Caution!
It cannot be guaranteed that the AIDE binaries, config file and
database are intact. It is not recommended that you run automated
AIDE checks without verifying AIDE yourself frequently. In addition
to that, AIDE does not implement any password or encryption
protection for its own files.
It is up to you how to put a file integrity checker to good effect.
On a compromised system, the intruder could disable the automated
check. Or he could replace the AIDE binary, config file and database
easily when they are not located on read-only media.

10
aide-check.service Normal file
View File

@ -0,0 +1,10 @@
[Unit]
Description=AIDE file integrity check
Documentation=man:aide(1) man:aide.conf(5)
[Service]
Type=oneshot
ExecStart=/usr/sbin/aide --check
SuccessExitStatus=0 1 2 3 4 5 6 7
Nice=19
IOSchedulingClass=idle

11
aide-check.timer Normal file
View File

@ -0,0 +1,11 @@
[Unit]
Description=Daily AIDE file integrity check
Documentation=man:aide(1) man:aide.conf(5)
[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true
[Install]
WantedBy=timers.target

View File

@ -0,0 +1,66 @@
diff --git a/src/conf_eval.c b/src/conf_eval.c
index 5774ce6..6503709 100644
--- a/src/conf_eval.c
+++ b/src/conf_eval.c
@@ -580,9 +580,9 @@ static void include_file(const char* file, bool execute, int include_depth, char
}
}
-void check_permissions(const char* path, struct stat *st, int linenumber, char *filename, char* linebuf) {
+static void check_permissions(const char* path, struct stat *st, const char *directive, int linenumber, char *filename, char* linebuf) {
if ((st->st_uid != geteuid() && st->st_uid != 0) || (st->st_mode & 002) != 0 || (st->st_mode & 020) != 0) {
- LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'@@x_include': bad ownership or modes for '%s' (please ensure it is neither group- nor world-writable and owned by the current user or root)", path)
+ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'%s': bad ownership or modes for '%s' (please ensure it is neither group- nor world-writable and owned by the current user or root)", directive, path)
exit(INVALID_CONFIGURELINE_ERROR);
}
}
@@ -611,13 +611,13 @@ static void include_directory(const char* dir, const char* rx, bool execute, cha
struct stat fs;
- if (execute) {
- if (stat(dir,&fs) == -1) {
- LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'@@x_include': stat for '%s' failed: %s", dir, strerror(errno))
- exit(INVALID_CONFIGURELINE_ERROR);
- }
- check_permissions(dir, &fs, linenumber, filename, linebuf);
+ /* stat() follows symlinks; we intentionally check the target's ownership
+ * and mode rather than the symlink node itself */
+ if (stat(dir,&fs) == -1) {
+ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'%s': stat for '%s' failed: %s", execute?"@@x_include":"@@include", dir, strerror(errno))
+ exit(INVALID_CONFIGURELINE_ERROR);
}
+ check_permissions(dir, &fs, execute?"@@x_include":"@@include", linenumber, filename, linebuf);
n = scandir(dir, &namelist, dirfilter, alphasort);
if (n == -1) {
@@ -660,9 +660,8 @@ static void include_directory(const char* dir, const char* rx, bool execute, cha
log_msg(LOG_LEVEL_DEBUG,"%s: skip '%s' (reason: file name does not match regex '%s')", dir, namelist[i]->d_name, rx);
} else {
int exec = execute && S_IXUSR&fs.st_mode;
- if (exec) {
- check_permissions(filepath, &fs, linenumber, filename, linebuf);
- }
+ /* pass directive name (not exec flag) so the error names the directive the user wrote */
+ check_permissions(filepath, &fs, execute?"@@x_include":"@@include", linenumber, filename, linebuf);
log_msg(LOG_LEVEL_CONFIG,"%s: %s '%s'", dir, exec?"execute":"include", namelist[i]->d_name);
include_file(filepath, exec, include_depth, nested_rule_prefix);
}
@@ -701,14 +700,15 @@ static void eval_include_statement(include_statement statement, int include_dept
} else {
struct stat fs;
if (lstat(path,&fs) == -1) {
- LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'@@include': lstat for '%s' failed: %s", path, strerror(errno))
+ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'%s': lstat for '%s' failed: %s", statement.execute?"@@x_include":"@@include", path, strerror(errno))
exit(INVALID_CONFIGURELINE_ERROR);
}
if (S_ISREG(fs.st_mode)) {
+ check_permissions(path, &fs, statement.execute?"@@x_include":"@@include", linenumber, filename, linebuf);
LOG_CONFIG_FORMAT_LINE_PREFIX(LOG_LEVEL_CONFIG, "include file '%s' (depth: %d)", path, include_depth)
include_file(path, statement.execute && S_IXUSR&fs.st_mode, include_depth, rule_prefix);
} else {
- LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'@@include': '%s' is not a regular file", path);
+ LOG_CONFIG_FORMAT_LINE(LOG_LEVEL_ERROR, "'%s': '%s' is not a regular file", statement.execute?"@@x_include":"@@include", path);
exit(INVALID_CONFIGURELINE_ERROR);
}
}

View File

@ -23,8 +23,8 @@ database_add_metadata=yes
# Warn about unrestricted rules during config check (default: false)
config_check_warn_unrestricted_rules=false
# Number of workers for parallel processing (default: 1, can use percentage)
num_workers=1
# Number of workers for parallel processing (AIDE default: 1, overridden to 4 here)
num_workers=4
# Default.
log_level=warning
@ -124,6 +124,10 @@ LOG = p+ftype+u+g+n+ANF+ARF+selinux+xattrs
# but we want to know when the data inside them changes - updated with modern hash
DATAONLY = ftype+p+l+n+u+g+s+acl+selinux+xattrs+sha256
# Read /etc/aide.d/*.conf files
@@include /etc/aide.d ^[a-zA-Z0-9_-]+\.conf$
# Next decide what directories/files you want in the database.
/boot NORMAL

View File

@ -1,7 +1,7 @@
Summary: Intrusion detection environment
Name: aide
Version: 0.19.2
Release: 6%{?dist}
Release: 7%{?dist}
URL: https://github.com/aide/aide
License: GPLv2+
@ -16,7 +16,10 @@ Source4: README.quickstart
Source5: aide.logrotate
Source6: aide-tmpfiles.conf
Source7: aide-migrate-config
Source8: aide-check.service
Source9: aide-check.timer
Patch0: aide-0.19.2-syslog-format.patch
Patch1: aide-include-permission-checks.patch
BuildRequires: gcc
BuildRequires: make
@ -69,6 +72,11 @@ mkdir -p -m0700 %{buildroot}%{_localstatedir}/lib/aide
# Install tmpfiles config
install -Dpm0644 %{SOURCE6} %{buildroot}%{_tmpfilesdir}/aide.conf
install -Dpm0755 %{SOURCE7} %{buildroot}%{_sbindir}/aide-migrate-config
# Create /etc/aide.d/
mkdir -p -m0700 %{buildroot}%{_sysconfdir}/aide.d
# Install systemd timer and service for scheduled integrity checks
install -Dpm0644 %{SOURCE8} %{buildroot}%{_unitdir}/aide-check.service
install -Dpm0644 %{SOURCE9} %{buildroot}%{_unitdir}/aide-check.timer
%files
%license COPYING
@ -80,17 +88,35 @@ install -Dpm0755 %{SOURCE7} %{buildroot}%{_sbindir}/aide-migrate-config
%{_mandir}/man5/*.5*
%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/aide.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/aide
%dir %attr(0700,root,root) %{_sysconfdir}/aide.d
%dir %attr(0700,root,root) %{_localstatedir}/lib/aide
%dir %attr(0700,root,root) %{_localstatedir}/log/aide
%{_tmpfilesdir}/aide.conf
%{_unitdir}/aide-check.service
%{_unitdir}/aide-check.timer
%post
%systemd_post aide-check.timer
if [ $1 -ge 2 ]; then
/usr/sbin/aide-migrate-config /etc/aide.conf 2>&1 | \
tee -a /var/log/aide/aide-migrate.log || :
fi
%preun
%systemd_preun aide-check.timer
%postun
%systemd_postun_with_restart aide-check.timer
%changelog
* Tue Jun 03 2026 Patrik Koncity <pkoncity@redhat.com> - 0.19.2-7
- Support for included files in /etc/aide.d/
Resolves: RHEL-178122
- Increase default values for num_workers
Resolves: RHEL-178123
- Add pre-configured systemd timer for aide check
Resolves: RHEL-178121
* Tue May 26 2026 Attila Lakatos <alakatos@redhat.com> - 0.19.2-6
- Add aide-migrate-config to automate config migration from pre-0.19 syntax
Resolves: RHEL-178317