# AppArmor profile for MariaDB 11.8 server daemon
#
# TESTING:
# - Monitor denials: journalctl -k --since=yesterday --follow --grep="apparmor"
# - Test in complain mode first: aa-complain /etc/apparmor.d/mariadbd
# - See confinement status: aa-status | grep -C 10 mariadb
# - Check specific denials: aa-logprof
# - Test all server functionality: systemctl restart mariadb
# - Verify plugin loading, backups, replication, all packaged Galera SST
#   mechanisms (both donor + joiner), etc.
#
# CONTAINMENT ERRORS:
# - Check syslog/journal for "apparmor=denied" messages
# - Look for "operation=open" denials for file access
# - Check for "operation=exec" denials for program execution
# - Monitor /var/log/audit/audit.log if auditd is installed
#
# PROFILE UPDATE WORKFLOW:
# 1. Identify denial in logs (operation, path, requested_mask)
# 2. Add appropriate rule to this profile
# 3. Reload profile: apparmor_parser -r /etc/apparmor.d/mariadbd
# 4. Test again in complain mode
# 5. Switch to enforce mode when confident: aa-enforce /etc/apparmor.d/mariadbd
# 6. Consider adding site-specific rules to /etc/apparmor.d/local/mariadbd

# Define RUN, HOMEDIRS etc globally
include <tunables/global>

profile mariadbd /usr/sbin/mariadbd flags=(complain) {

  # Including <abstractions/base> does not work on Ubuntu 24.04. The issue was
  # fixed upstream https://gitlab.com/apparmor/apparmor/-/merge_requests/1236
  # but has not landed on ubuntu 24.04 yet (tracking in
  # https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2065685)
  include <abstractions/base>
  include <abstractions/nameservice>
  include <abstractions/user-tmp>
  include <abstractions/mysql>
  include <abstractions/winbind>

  # Minimal essential rules traditionally provided by abstractions/base
  # These rules are commonly needed by system services and avoid the passt inclusion
  capability chown,
  capability fowner,
  # per systemd service file is used with --memlock to lock memory beyond the usual rlimit
  capability ipc_lock,
  # Galera gu_thread_setschedparam still uses this
  capability sys_nice,
  capability kill,
  network inet stream,
  network inet dgram,
  network unix stream,
  # Probably excessive/unnecessary:
  #@{PROC}/sys/kernel/ngroups_max r,
  #@{PROC}/@{pid}/fd/ r,
  #@{PROC}/@{pid}/stat r,

# Allow system resource access
  @{PROC}/@{pid}/cgroup r,
  @{PROC}/@{pid}/status r,
  @{PROC}/sys/kernel/core_pattern r,
  @{sys}/block/** r,
  @{sys}/block/*/queue/** r,
  @{sys}/devices/**/queue/** r,
  @{sys}/devices/system/cpu/ r,
  @{sys}/devices/system/node/ r,
  @{sys}/devices/system/node/** r,

  # Should not be necessary according to Daniel Black:
  #capability dac_override,
  #capability dac_read_search,
  # Should not be necessary as mariadbd does not run as root:
  #capability setuid,
  #capability setgid,

# Allow network access
  network tcp,

# Allow config access
  /etc/mysql/** r,
  /etc/systemd/system/mariadb.service.d/ r,
  /etc/systemd/system/mariadb.service.d/** r,

# Allow pid, socket, socket lock file access
  /run/mysqld/mysqld.pid rw,
  /run/mysqld/mysqld.sock rw,
  /run/mysqld/mysqld.sock.lock rw,

# Allow systemd notify messages
  /run/systemd/notify w,
  /run/systemd/private rw,

# Allow execution of server binary
  /usr/sbin/mariadbd mr,
  /usr/sbin/mysqld mr,

# Allow plugin access
  /usr/lib/{@{multiarch},mysql}/mariadb{,d}/plugin/ r,
  /usr/lib/{@{multiarch},mysql}/mariadb{,d}/plugin/*.so* mr,
  /usr/lib/mysql/plugin/ r,
  /usr/lib/mysql/plugin/*.so* mr,

# Allow error msg and charset access
  /usr/share/mariadb/ r,
  /usr/share/mariadb/** r,

# Allow data dir access
  /var/lib/mariadb/ r,
  /var/lib/mariadb/** rwk,
  /var/lib/mysql/ r,
  /var/lib/mysql/** rwk,

# Allow log file access
  /var/log/mariadb/ r,
  /var/log/mariadb/** rw,
  /var/log/mysql/ r,
  /var/log/mysql/** rw,

# Allow shared memory access
  /{run,dev}/shm/** rw,
  # More specific shared memory for MariaDB
  /run/mysqld/* rw,

# Allow read access to OpenSSL config
  /etc/ssl/openssl.cnf r,

# Memory pressure detection
  @{sys}/fs/cgroup/**/memory.pressure rw,

# For huge/large page support
  @{sys}/kernel/mm/hugepages/ r,
  @{sys}/kernel/mm/hugepages/** r,

# Innodb physical disk size introspection
  @{sys}/dev/block/*/queue/physical_block_size r,
  @{sys}/devices/**/queue/physical_block_size r,

# Deny invalid runbindable mount rule that causes parser errors
# This broad deny rule should override any problematic mount operations
# that might be included from system abstractions
  audit deny mount options=(runbindable),

  # Site-specific additions and overrides. See local/README for details.
  include if exists <local/mariadbd>
}
