# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2023-2024 Alexandre Pujol <alexandre@pujol.io>
# Copyright (C) 2023 monsieuremre <https://github.com/monsieuremre>
# SPDX-License-Identifier: GPL-2.0-only

# Profile for systemd (PID 1), it does not specify an attachment path because
# it is directly loaded by systemd.
#
# !!! danger
#
#     Only use this profile with a fully configured system. Otherwise it **WILL**
#     break your computer. See https://apparmor.pujol.io/full-system-policy/.
#
# !!! info
#
#     Distributions and other programs can add rules in the `usr/systemd.d` directory
#
# Overall architecture of the systemd profiles:
#
# ```
# systemd                                # PID 1, entrypoint, requires "Early policy"
# ├── systemd                            # To restart itself
# ├── systemd-generators-*               # Systemd system and environment generators
# └── sd                                 # Internal service starter and config handler, handles all services
#     ├── px or px,                      # Any service with profile
#     ├── px ->                          # Any service without profile defined in the unit file (see systemd/full/systemd)
#     ├── &*                             # Stacked service as defined in the unit file (see systemd/full/systemd)
#     ├── sd-mount                       # Handles all mounts from services
#     ├── sd//systemctl                  # Internal system systemctl
#     └── systemd-user                   # Profile for 'systemd --user'
#         ├── systemd-user               # To restart itself
#         ├── systemd-user-generators-*  # Systemd user and environment generators
#         └── sdu                        # Handles all user services
#             ├── px or px,              # Any user service with profile
#             ├── px ->                  # Any user service without profile defined in the unit file (see systemd/full/systemd)
#             ├── &*                     # Stacked user service as defined in the unit file (see systemd/full/systemd)
#             └── sdu//systemctl         # Internal user systemctl
# ```
#
# Advantages:
#
# - Differentiate systemd (PID 1) and `system --user`
# - Keep `systemd` and systemd-user as mininal as possible, and transition to less privileged profiles.
# - Allow the executor profiles to handle stacked profiles.
# - Most additions need to be done in the `sd`/`sdu` profile, not in `systemd`/`systemd-user`.
# - Dedicated `sd-mount` profile for most mount from the unit services.
#
# !!! warning "Work in Progress"
#
#     This profile stack can be changed to provide a more controlled environment:
#
#     - No global allow anymore: in high security environments, we must manage the list
#       of program/service that can be started by systemd and ensure that they are all
#       listed and confined. Programs not listed will not be able to start.
#     - Outside common systemd service, the list may have to be automatically
#       generated at install time, in `/etc/apparmor.d/usr/systemd.d/exec`
#

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{lib}/systemd/systemd
@{att} = /att/systemd/
profile systemd flags=(attach_disconnected,attach_disconnected.path=@{att},mediate_deleted,complain) {
  include <abstractions/attached/base>
  include <abstractions/bus-system>
  include <abstractions/disks-read>
  include <abstractions/attached/nameservice-strict>
  include <abstractions/sys/dmi>
  include <abstractions/wutmp>

  capability audit_control,
  capability audit_read,
  capability audit_write,
  capability bpf,
  capability chown,
  capability dac_override,
  capability dac_read_search,
  capability fowner,
  capability fsetid,
  capability kill,
  capability net_admin,
  capability net_bind_service,
  capability perfmon,
  capability setpcap,
  capability sys_admin,
  capability sys_boot,
  capability sys_ptrace,
  capability sys_resource,
  capability sys_tty_config,

  network inet dgram,
  network inet stream,
  network inet6 dgram,
  network inet6 stream,
  network netlink raw,
  network vsock stream,

  mount fstype=autofs                                                 systemd-1 -> @{PROC}/sys/fs/binfmt_misc/,
  mount fstype=autofs                                                 systemd-1 -> @{efi}/,
  mount fstype=tmpfs                                                      tmpfs -> /tmp/,

  mount options=(rw make-rslave)                                                   /,

  remount                                        @{HOME}/{,**},
  remount                                        @{HOMEDIRS}/,
  remount                                        @{MOUNTDIRS}/,
  remount                                        @{MOUNTS}/{,**},
  remount                                        /snap/{,**},
  remount options=(ro bind nodev noexec nosuid)  /dev/mqueue/,
  remount options=(ro bind nodev nosuid)         /dev/hugepages/,
  remount options=(ro bind noexec nosuid)        /dev/pts/,
  remount options=(ro bind nosuid)               /dev/,
  remount options=(ro bind)                      @{efi}/,
  remount options=(ro bind)                      /,

  umount @{PROC}/sys/fs/binfmt_misc/,
  umount @{run}/credentials/*/,

  mqueue (read getattr) type=posix /,

  signal send,

  ptrace (read, readby),

  unix type=dgram,
  unix type=stream,

  #aa/dbus own bus=system name=org.freedesktop.systemd1
  include <abstractions/bus/system/own>
  dbus bind bus=system name=org.freedesktop.systemd1{,.*},
  dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.systemd1{,.*}
       peer=(name="@{busname}"),
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.systemd1{,.*}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  # DBus.Properties: reply to properties request from anyone
  dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  # DBus.Introspectable: allow clients to introspect the service
  dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="@{busname}"),
  # DBus.ObjectManager: allow clients to enumerate sources
  dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*}}"),
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.DBus}"),


  @{exec_path} mrix,
  @{sh_path} mr,

  # Systemd internal service starter and config handler (sandboxing, namespacing, cgroup, etc.)
  @{lib}/systemd/systemd-executor                 mpx -> sd,

  # Systemd system generators. Profiles must exist
  @{lib}/netplan/generate                         mpx,
  @{lib}/systemd/system-environment-generators/*  mpx,
  @{lib}/systemd/system-generators/*              mpx,

  @{etc_ro}/environment r,
  @{etc_ro}/environment.d/{,**} r,
  /etc/acpi/events/{,**} r,
  /etc/binfmt.d/{,**} r,
  /etc/conf.d/{,**} r,
  /etc/default/{,**} r,
  /etc/machine-id r,
  /etc/modules-load.d/{,**} r,
  /etc/networkd-dispatcher/{,**} r,
  /etc/systemd/{,**} r,
  /etc/systemd/system/** w,
  /etc/udev/hwdb.d/{,**} r,

  @{efi}/ r,
  /snap/*/@{int}/ r,

        /tmp/ r,
        /var/tmp/ r,
  owner /tmp/systemd-private-*/{,**} rw,
  owner /var/tmp/systemd-private-*/{,**} rw,

  @{att}@{run}/systemd/journal/dev-log r,
  @{att}@{run}/systemd/journal/socket r,
  @{att}@{run}/systemd/notify r,

  @{run}/ rw,
  @{run}/* rw,
  @{run}/*/ rw,
  @{run}/*/* rw,
  @{run}/credentials/{,**} rw,
  @{run}/systemd/{,**} rw,

  @{run}/udev/data/+module:* r,           # Identifies kernel modules loaded by udev
  @{run}/udev/data/c4:@{int} r,           # For TTY devices
  @{run}/udev/data/c5:@{int}   r,         # for /dev/tty, /dev/console, /dev/ptmx
  @{run}/udev/data/c10:@{int}   r,        # For non-serial mice, misc features
  @{run}/udev/data/c116:@{int} r,         # For ALSA
  @{run}/udev/data/c@{dynamic}:@{int} r,  # For dynamic assignment range 234 to 254, 384 to 511
  @{run}/udev/data/n@{int} r,             # For network interfaces
  @{run}/udev/tags/systemd/ r,

  @{sys}/**/uevent r,
  @{sys}/bus/ r,
  @{sys}/class/ r,
  @{sys}/class/power_supply/ r,
  @{sys}/devices/virtual/tty/console/active r,
  @{sys}/firmware/efi/efivars/LoaderSystemToken-@{uuid} rw,
  @{sys}/fs/cgroup/{,**} rw,
  @{sys}/fs/fuse/connections/ r,
  @{sys}/fs/pstore/ r,
  @{sys}/kernel/**/ r,
  @{sys}/module/apparmor/parameters/enabled r,
  @{sys}/module/vt/parameters/default_utf8 r,

        @{PROC}/@{pid}/cgroup r,
        @{PROC}/@{pid}/cmdline r,
        @{PROC}/@{pid}/comm r,
        @{PROC}/@{pid}/fd/ r,
        @{PROC}/@{pid}/stat r,
        @{PROC}/cmdline r,
        @{PROC}/devices r,
        @{PROC}/pressure/* r,
        @{PROC}/swaps r,
        @{PROC}/sys/fs/binfmt_misc/ r,
        @{PROC}/sys/fs/nr_open r,
        @{PROC}/sys/kernel/* r,
        @{PROC}/sys/kernel/random/boot_id r,
        @{PROC}/sysvipc/msg r,
        @{PROC}/sysvipc/sem r,
        @{PROC}/sysvipc/shm r,
  owner @{PROC}/@{pid}/mountinfo r,
  owner @{PROC}/1/coredump_filter r,
  owner @{PROC}/1/fdinfo/@{int} r,
  owner @{PROC}/1/gid_map r,
  owner @{PROC}/1/oom_score_adj rw,
  owner @{PROC}/1/setgroups r,
  owner @{PROC}/1/uid_map r,

        /dev/autofs r,
        /dev/dri/card@{int} rw,
        /dev/initctl w,
        /dev/input/ r,
        /dev/kmsg w,
        /dev/tty rw,
        /dev/tty@{u8} rw,
  owner /dev/console rwk,
  owner /dev/hugepages/ rw,
  owner /dev/input/event@{int} rw,
  owner /dev/mqueue/ rw,
  owner /dev/rfkill rw,
  owner /dev/shm/ r,
  owner /dev/ttyS@{int} rwk,

  include if exists <usr/systemd.d>
  include if exists <local/systemd>
}

# vim:syntax=apparmor
