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

#aa:lint ignore=too-wide

# Profile for `systemd --user`, not PID 1 but the user manager for any UID.
# It does not specify an attachment path because it is intended to be used only
# via `px -> systemd-user` exec transitions from the `systemd` profile.
#
# !!! 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-user.d` directory
#

abi <abi/4.0>,

include <tunables/global>

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

  network netlink raw,

  signal send,

  ptrace read,

  unix type=dgram peer=(label=@{p_sdu}),

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

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


  dbus receive bus=session
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"),

  @{exec_path} mrix,

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

  # Systemd user generators. Profiles must exist
  @{lib}/systemd/user-environment-generators/*     px,
  @{lib}/systemd/user-generators/*                 px,

  @{etc_ro}/environment r,
  /etc/systemd/user.conf r,
  /etc/systemd/user.conf.d/{,**} r,
  /etc/systemd/user/{,**} r,

  owner @{user_config_dirs}/systemd/user/{,**} rw,

  owner @{run}/user/@{uid}/ rw,
  owner @{run}/user/@{uid}/** rwlk,

  @{run}/mount/utab r,
  @{run}/systemd/oom/io.systemd.ManagedOOM 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}/devices/**/uevent r,
        @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} r,
  owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} rw,

        @{PROC}/@{pid}/cgroup r,
        @{PROC}/@{pid}/comm r,
        @{PROC}/@{pid}/stat r,
        @{PROC}/1/environ r,
        @{PROC}/cmdline r,
        @{PROC}/pressure/* r,
        @{PROC}/swaps r,
        @{PROC}/sys/fs/nr_open r,
        @{PROC}/sys/kernel/osrelease r,
        @{PROC}/sys/kernel/overflowgid r,
        @{PROC}/sys/kernel/overflowuid r,
        @{PROC}/sys/kernel/pid_max r,
        @{PROC}/sys/kernel/random/boot_id r,
        @{PROC}/sys/kernel/threads-max r,
  owner @{PROC}/@{pid}/cmdline r,
  owner @{PROC}/@{pid}/fdinfo/@{int} r,
  owner @{PROC}/@{pid}/gid_map r,
  owner @{PROC}/@{pid}/mountinfo r,
  owner @{PROC}/@{pid}/oom_score_adj rw,
  owner @{PROC}/@{pid}/uid_map r,
  owner @{PROC}/@{pids}/fd/ r,

  deny capability bpf,
  deny capability dac_override,
  deny capability dac_read_search,
  deny capability mknod,
  deny capability net_admin,
  deny capability perfmon,
  deny capability sys_admin,
  deny capability sys_boot,
  deny capability sys_resource,

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

# vim:syntax=apparmor
