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

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{bin}/sddm
@{att} = /att/sddm/
profile sddm /{,usr/}bin/sddm flags=(attach_disconnected,attach_disconnected.path=@{att},mediate_deleted) {
  include <abstractions/attached/base>
  include <abstractions/authentication>
  include <abstractions/bus/system/org.freedesktop.login1>
  include <abstractions/fontconfig-cache-read>
  include <abstractions/graphics>
  include <abstractions/kde-strict>
  include <abstractions/attached/nameservice-strict>
  include <abstractions/upower-observe>
  include <abstractions/wutmp>

  capability audit_write,
  capability chown,
  capability dac_override,
  capability dac_read_search,
  capability fowner,
  capability kill,
  capability net_admin,
  capability setgid,
  capability setuid,
  capability sys_tty_config,

  network netlink raw,

  signal (send) set=(kill, term) peer=startplasma,
  signal (send) set=(kill, term) peer=xorg,

  unix type=stream addr=@@{udbus}/bus/sddm-helper/system,

  #aa/dbus own bus=system name=org.freedesktop.DisplayManager
  include <abstractions/bus/system/own>
  dbus bind bus=system name=org.freedesktop.DisplayManager{,.*},
  dbus receive bus=system path=/org/freedesktop/DisplayManager{,/**}
       interface=org.freedesktop.DisplayManager{,.*}
       peer=(name="@{busname}"),
  dbus send bus=system path=/org/freedesktop/DisplayManager{,/**}
       interface=org.freedesktop.DisplayManager{,.*}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  # DBus.Properties: reply to properties request from anyone
  dbus (send receive) bus=system path=/org/freedesktop/DisplayManager{,/**}
       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/DisplayManager{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="@{busname}"),
  # DBus.ObjectManager: allow clients to enumerate sources
  dbus receive bus=system path=/org/freedesktop/DisplayManager{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.DisplayManager{,.*}}"),
  dbus send bus=system path=/org/freedesktop/DisplayManager{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.DBus}"),


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

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


  @{exec_path} mr,

  @{bin}/ksecretd                             px,
  @{bin}/kwalletd[56]                         px,
  @{bin}/sddm-greeter{,-qt6}                  px,
  @{bin}/Xorg                                 px,
  @{lib}/{,sddm/}sddm-helper                 rix,
  @{lib}/@{multiarch}/sddm/sddm-helper       rix,

  # Hanlde all sddm/scripts
  @{shells_path}                              cx -> shell,
  /usr/share/sddm/scripts/Xsetup             rix,
  /usr/share/sddm/scripts/Xstop              rix,
  /usr/share/sddm/scripts/Xsession           rix,

    @{lib}/{,sddm/}sddm-helper-start-wayland rix,
    /usr/share/sddm/scripts/wayland-session  rix,
    @{etc_ro}/sddm/wayland-session            px,

    /usr/share/wayland-sessions/{,*.desktop} r,

    owner @{user_share_dirs}/sddm/wayland-session.log w,

    @{bin}/xmodmap                           pux,
    @{bin}/xrdb                               px,
    @{bin}/xset                               px,
    @{bin}/xsetroot                           px,
    @{sbin}/checkproc                        rix,
    @{lib}/{,sddm/}sddm-helper-start-x11user rix,

    @{etc_ro}/sddm/Xsession                   px,
    @{etc_ro}/X11/xdm/Xsession                px,
    @{etc_ro}/X11/xdm/Xsetup                 rix,
    @{etc_ro}/X11/Xmodmap r,

    owner @{user_share_dirs}/sddm/xorg-session.log w,

  /usr/share/sddm/themes/** r,

  /etc/manpath.config r,
  /etc/default/locale r,
  /etc/locale.conf r,
  /etc/sddm.conf r,
  /etc/sddm.conf.d/{,*} r,
  /etc/shells r,
  /etc/sysconfig/console r,
  /etc/sysconfig/displaymanager r,
  /etc/sysconfig/language r,
  /etc/sysconfig/mail r,
  /etc/sysconfig/proxy r,
  /etc/sysconfig/windowmanager r,

  / r,

  /var/lib/lastlog/ r,
  /var/lib/lastlog/* rwk,

  /var/lib/wtmpdb/ r,
  /var/lib/wtmpdb/* rwk,

        @{SDDM_HOME}/state.conf rw,
  owner @{SDDM_HOME}/** rw,
  owner @{sddm_cache_dirs}/sddm-greeter/qmlcache/*.jsc mrw,
  owner @{sddm_cache_dirs}/sddm-greeter/qmlcache/*.qmlc mrw,

  owner @{HOME}/ r,
  owner @{HOME}/.local/ w,
  owner @{HOME}/.Xauthority rw,

  owner @{user_config_dirs}/menus/{,**} r,
  owner @{user_config_dirs}/startkderc r,

  owner @{user_share_dirs}/kwalletd/ rw,
  owner @{user_share_dirs}/kwalletd/kdewallet.salt rw,
  owner @{user_share_dirs}/sddm/ w,

        /tmp/sddm-:@{u8}-@{rand6} rw,
        /tmp/xauth_@{rand6} rwl -> /tmp/#@{int},
  owner /tmp/.@{rand6}/{,s} rw,
  owner /tmp/#@{int} rw,
  owner /tmp/sddm-auth-@{uuid} rw,

        @{run}/systemd/io.systemd.Login rw,
  @{att}@{run}/systemd/sessions/{,@{l}}@{int}.ref rw,

        @{run}/faillock/@{user} rwk,
        @{run}/sddm.pid rw,
        @{run}/sddm/\{@{uuid}\} rw,
        @{run}/sddm/#@{int} rw,
        @{run}/sddm/xauth_@{rand6} rwl -> @{run}/sddm/#@{int},
        @{run}/user/@{uid}/xauth_@{rand6} rwl,
  owner @{run}/sddm/ rw,
  owner @{run}/user/@{uid}/ r,
  owner @{run}/user/@{uid}/#@{int} rw,
  owner @{run}/user/@{uid}/kwallet5.socket rw,

        @{PROC}/ r,
        @{PROC}/uptime r,
  owner @{PROC}/@{pid}/loginuid rw,
  owner @{PROC}/@{pid}/mounts r,
  owner @{PROC}/@{pid}/uid_map r,
  owner @{PROC}/1/limits r,

  /dev/tty@{u8} rw,
  /dev/tty rw,

  profile shell {
    include <abstractions/attached/base>
    include <abstractions/attached/consoles>
    include <abstractions/shells>

    ptrace read,

    @{shells_path} mrix,
    @{coreutils_path}    rix,
    @{bin}/disable-paste rix,
    @{bin}/locale        rix,
    @{bin}/manpath       rix,
    @{bin}/xdm           r,
    @{bin}/xmodmap       rix,
    @{bin}/zoxide        rix,
    @{sbin}/checkproc    rix,

    @{bin}/flatpak        px,
    @{bin}/pacman         px -> sddm//pacman,
    @{bin}/pidof          px,
    @{bin}/systemctl      px -> sddm//systemctl,
    @{bin}/vapoursynth    px,

    @{bin}/dbus-run-session                    px -> dbus-session,
    @{bin}/dbus-update-activation-environment  px -> dbus-session,
    @{lib}/plasma-dbus-run-session-if-needed  rix,
    @{lib}/@{multiarch}/libexec/plasma-dbus-run-session-if-needed  rix,

        @{bin}/startplasma-wayland  px,

        owner @{user_share_dirs}/sddm/wayland-session.log w,

        @{bin}/startplasma-x11      px,

        owner @{user_share_dirs}/sddm/xorg-session.log w,


    # Note: the condition are useless, this is experimental.
      @{bin}/Hyprland             px,
      @{bin}/start-hyprland       px,
      @{bin}/startlxqt            px,
      @{bin}/startlxqtwayland     px,
      @{bin}/sway                pux,
      @{bin}/openbox-session     pux,

    /usr/share/sddm/scripts/{,**} r,

    /etc/debuginfod/{,*} r,
    /etc/X11/xinit/xinitrc.d/{,*} r,

    owner @{PROC}/@{pid}/fd/ r,

    include if exists <local/sddm_shell>
  }

  profile systemctl {
    include <abstractions/attached/base>
    include <abstractions/app/systemctl>

    include if exists <local/sddm_systemctl>
  }

  profile xauth {
    include <abstractions/attached/base>

    @{bin}/xauth mr,

    owner @{HOME}/.Xauthority-c rw,
    owner @{HOME}/.Xauthority-l rwl -> @{HOME}/.Xauthority-c,
    owner @{HOME}/.Xauthority-n rw,
    owner @{HOME}/.Xauthority   rwl -> @{HOME}/.Xauthority-n,

    owner @{user_share_dirs}/sddm/xorg-session.log w,

    owner @{run}/sddm/\{@{uuid}\}-c rw,
    owner @{run}/sddm/\{@{uuid}\}-l rwl -> @{run}/sddm/\{@{uuid}\}-c,
    owner @{run}/sddm/\{@{uuid}\}-n rw,
    owner @{run}/sddm/\{@{uuid}\}   rwl -> @{run}/sddm/\{@{uuid}\}-n,

    include if exists <local/sddm_xauth>
  }

  profile pacman {
    include <abstractions/attached/base>

    @{bin}/pacman mr,

    /var/lib/pacman/local/{,**} r,

    include if exists <local/sddm_pacman>
  }

  include if exists <local/sddm>
}

# vim:syntax=apparmor
