# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2020-2021 Mikhail Morfikov
# Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{bin}/systemd-analyze
@{att} = /att/systemd-analyze/
profile systemd-analyze /{,usr/}bin/systemd-analyze flags=(attach_disconnected,attach_disconnected.path=@{att}) {
  include <abstractions/attached/base>
  include <abstractions/bus-system>
  include <abstractions/bus/system/org.freedesktop.hostname1>
  include <abstractions/common/systemd>
  include <abstractions/attached/consoles>
  include <abstractions/sys/dmi-full>
  include <abstractions/sys/firmware>
  include <abstractions/tpm>

  capability net_admin,
  capability sys_admin,
  capability sys_chroot,
  capability sys_ptrace,
  capability sys_resource,

  network inet dgram,
  network netlink raw,

  signal (send) peer=child-pager,

  ptrace read,

  unix bind type=stream addr=@@{udbus}/bus/systemd-analyze/,
  unix bind type=stream addr=@@{udbus}/bus/systemd-analyze/system,

  #aa/dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}"
  # Unix: allow connection to the profile
  unix type=stream peer=(label="@{p_systemd}"),
  # org.freedesktop.systemd1: send and receive anything to the interface on the specific peer label
  dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.systemd1{,.*}
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*},org.freedesktop.DBus}", label="@{p_systemd}"),
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.systemd1{,.*}
       peer=(name="org.freedesktop.systemd1{,.*}"),
  # DBus.Properties: read and send properties
  dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*},org.freedesktop.DBus}", label="@{p_systemd}"),
  # DBus.Introspectable: allow service introspection
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*},org.freedesktop.DBus}", label="@{p_systemd}"),
  # DBus.ObjectManager: allow clients to enumerate sources
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*},org.freedesktop.DBus}", label="@{p_systemd}"),
  dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*},org.freedesktop.DBus}", label="@{p_systemd}"),


  @{exec_path} mr,

  @{lib}/systemd/system-environment-generators/* rix,

  @{pager_path} rpx -> child-pager,
  @{sh_path}   mrcx -> shell,
  @{bin}/gdb     cx -> gdb,
  @{bin}/man    rpx,

  /usr/ r,
  @{lib}/systemd/** r,

  /usr/share/misc/termcap r,

  # Needed for cat-config command
  #aa:lint ignore=too-wide
  /etc/* r,
  /etc/*.d/{,*} r,
  /etc/console-setup/vtrgb r,
  /etc/default/keyboard r,
  /etc/default/locale r,
  /etc/systemd/** r,

  owner @{tmp}/systemd-temporary-*/ rw,

  @{att}@{run}/systemd/private rw,

  @{run}/modprobe.d/{,*} r,
  @{run}/motd.d/{,*} r,
  @{run}/systemd/generator/ r,
  @{run}/systemd/private rw,
  @{run}/systemd/resolve/stub-resolv.conf r,
  @{run}/systemd/system/ r,
  @{run}/systemd/transient/ r,
  @{run}/systemd/userdb/io.systemd.DynamicUser w,
  @{run}/udev/data/+*:* r,                # Identifies all subsystems
  @{run}/udev/data/c@{int}:@{int} r,      # Identifies all character devices
  @{run}/udev/tags/systemd/ r,
  @{run}/tmpfiles.d/{,*} r,

  @{sys}/bus/ r,
  @{sys}/class/ r,
  @{sys}/class/drm/ r,
  @{sys}/devices/**/uevent r,
  @{sys}/devices/@{pci}/drm/card@{int}/*/edid r,
  @{sys}/firmware/acpi/tables/FPDT r,
  @{sys}/fs/cgroup/{,**} r,
  @{sys}/fs/cgroup/{systemd,unified}/**/cgroup.procs rw,
  @{sys}/fs/cgroup/unified/**/init.scope/ rw,
  @{sys}/module/**/uevent r,

  @{sys}/devices/virtual/dmi/id/ r,
  @{sys}/firmware/efi/efivars/LoaderTimeInitUSec-@{uuid} r,
  @{sys}/firmware/efi/efivars/LoaderTimeExecUSec-@{uuid} r,

        @{PROC}/@{pids}/gid_map r,
        @{PROC}/@{pids}/setgroups r,
        @{PROC}/swaps r,
        @{PROC}/sys/fs/nr_open r,
  owner @{PROC}/@{pid}/cgroup r,
  owner @{PROC}/@{pid}/comm r,
  owner @{PROC}/@{pid}/mountinfo r,
  owner @{PROC}/@{pid}/mounts r,

  profile gdb flags=(attach_disconnected,attach_disconnected.path=@{att}) {
    include <abstractions/attached/base>
    include <abstractions/python>

    capability dac_read_search,
    capability sys_ptrace,

    ptrace (read trace),

    @{bin}/iconv rix,

    @{bin}/** r,
    @{lib}/** r,

    /usr/share/gcc-@{int2}/python/{,**} r,
    /usr/share/gcc/** r,
    /usr/share/gdb/** r,
    /usr/share/gdb/python/{,**/}__pycache__/ w,
    /usr/share/gdb/python/{,**/}__pycache__/**.pyc w,
    /usr/share/gdb/python/{,**/}__pycache__/**.pyc.@{u64} w,
    /usr/share/glib-2.0/gdb/{,**} r,
    /usr/share/glib-2.0/gdb/__pycache__/ w,
    /usr/share/glib-2.0/gdb/__pycache__/**.pyc w,
    /usr/share/glib-2.0/gdb/__pycache__/**.pyc.@{u64} w,
    /usr/share/terminfo/** r,

    /etc/gdb/gdbinit r,
    /etc/inputrc r,

    @{PROC}/@{pids}/fd/ r,
    @{PROC}/@{pids}/mem rw,
    @{PROC}/@{pids}/task/ r,
    @{PROC}/@{pids}/task/@{tid}/maps r,
    @{PROC}/@{pids}/task/@{tid}/mem rw,
    @{PROC}/@{pids}/task/@{tid}/stat r,

    include if exists <local/systemd-analyze_gdb>
  }

  # unit-shell command
  profile shell flags=(attach_disconnected,attach_disconnected.path=@{att}) {
    include <abstractions/attached/base>
    include <abstractions/attached/nameservice-strict>
    include <abstractions/shells>

    capability dac_read_search,

    @{sh_path} r,

    # ToDo: Possibly could be limited to binaries used by all systemd unit files
    @{bin}/** pux,
    @{lib}/** pux,

    /usr/share/im-config/{,**} r,
    /usr/share/libdebuginfod-common/debuginfod.sh r,

    /etc/init.d/{,*} r,
    /etc/machine-id r,
    /etc/profile r,
    /etc/profile.d/{,*.sh} r,

    @{PROC}/sys/kernel/random/uuid r,

    /dev/tty rw,

    include if exists <local/systemd-analyze_shell>
  }

  include if exists <local/systemd-analyze>
}

# vim:syntax=apparmor
