# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2025 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only
# LOGPROF-SUGGEST: no
# NEEDS-VARIABLE: appid
# NEEDS-VARIABLE: att

# Default rules for all flatpak applications. Ideally, they should be
# generated with settings from the flatpak metadata.

# Security objectives:
# 1. Split the sandbox handler (bwrap) from the app profile (fapp)
# 2. Provide defence in depth, as flatpak already provides a sandbox
# 3. The main purpose of this profile is to ensure all processes are confined

# Notable security improvements over no profile at all:
# - No capabilities (except dac_override & dac_read_search)
# - Restrict unix socket to profiles defined in apparmor.d
# - Limit dbus system communication to profiles defined in apparmor.d
# - Ensure flatpak-spawn and host-spawn are confined too
# - Filter /proc/, /sys/ access

# Keep in mind that the profile is still common for all apps and is therefore
# way more permissive than a per-app profile would be.

# Abstractions in 'abstractions/flatpak' closelly follow the sandbox defined by
# flatpak, and are therefore different to they host equivalents, as flatpak apps
# do not have access to the full host filesystem.

  abi <abi/4.0>,

  include <abstractions/accessibility>
  include <abstractions/bus-session>
  include <abstractions/bus-system>
  include <abstractions/consoles>
  include <abstractions/nameservice-strict>

  # The app base platform, similar to our desktop abstraction, but with flatpak paths
  include <abstractions/flatpak/platform/org.freedesktop>

  # Base app specific rules, they are all included as it is for a generic profile
  include <abstractions/flatpak/baseapp/org.chromium.Chromium>
  include <abstractions/flatpak/baseapp/com.valvesoftware.Steam>

  # Flatpak devices '--device='
  include <abstractions/flatpak/devices/all>
  include <abstractions/flatpak/devices/shm>

  # Flatpack share (IPC, network) with the host '--share='
  include <abstractions/flatpak/shared/ipc>
  include <abstractions/flatpak/shared/network>

  # Flatpack sockets '--socket='
  include <abstractions/flatpak/sockets/cups>
  include <abstractions/flatpak/sockets/fallback-x11>
  include <abstractions/flatpak/sockets/gpg-agent>
  include <abstractions/flatpak/sockets/inherit-wayland-socket>
  include <abstractions/flatpak/sockets/pcsc>
  include <abstractions/flatpak/sockets/pulseaudio>
  include <abstractions/flatpak/sockets/session-bus>
  include <abstractions/flatpak/sockets/ssh-auth>
  include <abstractions/flatpak/sockets/system-bus>
  include <abstractions/flatpak/sockets/wayland>
  include <abstractions/flatpak/sockets/x11>

  # Flatpak filesystem access '--filesystem='
  # As a generic profile cannot filter filesystem for each app, this gives
  # full access to the user's home, and read only acccess to host system files.
  # In the limmit of what is allowed by flatpak.
  include <abstractions/flatpak/filesystem>

  # System bus: all system dbus interfaces a flatpak app can access
  include <abstractions/avahi-observe>
  include <abstractions/bluetooth-observe>
  include <abstractions/bus/org.freedesktop.hostname1>
  include <abstractions/bus/org.freedesktop.UDisks2>
  include <abstractions/bus/system/org.freedesktop.login1>
  include <abstractions/bus/system/org.freedesktop.systemd1.Manager>
  include <abstractions/bus/system/org.freedesktop.UPower>
  include <abstractions/network-manager-observe>

  capability dac_override,
  capability dac_read_search,

  unix type=seqpacket peer=(label=dbus-session),
  unix type=seqpacket peer=(label=flatpak-portal),
  unix type=seqpacket peer=(label=flatpak),
  unix type=seqpacket peer=(label=xdg-dbus-proxy),
  unix type=stream    peer=(label=dbus-session),
  unix type=stream    peer=(label=flatpak),
  unix type=stream    peer=(label=gnome-keyring-daemon),
  unix type=stream    peer=(label=unconfined),
  unix type=stream    peer=(label=xdg-dbus-proxy),
  unix type=stream    peer=(label=xdg-desktop-portal),

  signal (send receive) peer=fapp,
  signal (send receive) peer=fapp//&fbwrap,
  signal (send receive) peer=fbwrap,
  signal receive peer=flatpak-portal,

  ptrace read peer=fapp,
  ptrace read peer=fapp//&fbwrap,
  ptrace read peer=fbwrap,
  ptrace trace peer=fapp,
  ptrace trace peer=fapp//&fbwrap,
  ptrace trace peer=fbwrap,

  # As a generic profile, we cannot restrict the session bus, and we trust flatpak on this.
  dbus bus=session,

  # Run in the flatpak sandbox, the app
  /app/         rk,
  /app/**    mrkix,

  # Run in the flatpak sandbox, the app runtime
  @{bin}/        r,
  @{bin}/**    rix,
  @{lib}/        r,
  @{lib}/**    rix,
  @{sbin}/       r,
  @{sbin}/**   rix,

        / r,
  owner /.flatpak-info r,

  # In the sandbox, they are the same than ~/.var/app/@{appid}/{cache,config,data,cache/tmp}
  #aa:lint ignore=too-wide
  owner /var/cache/** rwlk,
  owner /var/config/** rwlk,
  owner /var/data/** rwlk,
  owner /var/tmp/** rwlk,

  owner @{att}@{HOME}/ r,
  owner @{att}@{HOME}/.var/app/@{appid}/ r,
  owner @{att}@{HOME}/.var/app/@{appid}/** mrwlk,
  owner @{HOME}/.var/app/@{appid}/ r,
  owner @{HOME}/.var/app/@{appid}/** mrwlk -> @{HOME}/.var/app/@{appid}/**,
  owner @{HOME}/.var/app/@{appid}/** ix,

        @{run}/parent/** mrix,
        @{run}/parent/usr/.ref rk,
        @{run}/parent/app/.ref rk,

  owner @{run}/flatpak/app/@{appid}/ r,
  owner @{run}/flatpak/app/@{appid}/** mrwlk -> @{run}/flatpak/app/@{appid}/**,

  owner @{run}/flatpak/doc/ r,
  owner @{run}/flatpak/doc/** mr,
  owner @{run}/flatpak/ld.so.conf.d/ r,
  owner @{run}/flatpak/ld.so.conf.d/*.conf r,

  owner @{run}/user/@{uid}/app/@{appid}/ r,
  owner @{run}/user/@{uid}/app/@{appid}/** rwlk -> @{run}/user/@{uid}/app/@{appid}/**,

        @{run}/host/os-release r,
  owner @{run}/host/ r,
  owner @{run}/host/container-manager r,

  #aa:lint ignore=too-wide
  # Flatpak creates an app-specific private restricted /tmp. As such, we can
  # simply allow full access to /tmp.
        /tmp/   r,
  owner /tmp/** mrwlkix,

  # Show the list of active tty
  @{sys}/devices/virtual/tty/tty@{int}/active r,

  # This is an information leak
  owner @{PROC}/@{pid}/mountinfo r,

  # Reads of oom_adj and oom_score_adj are safe
  owner @{PROC}/@{pid}/oom_adj r,
  owner @{PROC}/@{pid}/oom_score_adj r,

  # Per man(5) proc, the kernel enforces that a thread may only modify its comm
  # value or those in its thread group.
  owner @{PROC}/@{pid}/task/@{tid}/comm rw,

        @{PROC}/ r,
        @{PROC}/@{pid}/cpuset r,
        @{PROC}/@{pid}/fd/ r,
        @{PROC}/@{pid}/io r,
        @{PROC}/@{pid}/maps r,
        @{PROC}/@{pid}/smaps r,
        @{PROC}/@{pid}/stat r,
        @{PROC}/@{pid}/statm r,
        @{PROC}/@{pid}/status r,
        @{PROC}/@{pid}/task/@{tid}/status r,
        @{PROC}/loadavg r,
        @{PROC}/sys/fs/file-max r,
        @{PROC}/sys/fs/file-nr r,
        @{PROC}/sys/fs/inotify/max_queued_events r,
        @{PROC}/sys/fs/inotify/max_user_instances r,
        @{PROC}/sys/fs/inotify/max_user_watches r,
        @{PROC}/sys/fs/nr_open r,
        @{PROC}/sys/fs/pipe-max-size r,
        @{PROC}/sys/kernel/hostname r,
        @{PROC}/sys/kernel/osrelease r,
        @{PROC}/sys/kernel/ostype r,
        @{PROC}/sys/kernel/pid_max r,
        @{PROC}/sys/kernel/random/boot_id r,
        @{PROC}/sys/kernel/random/entropy_avail r,
        @{PROC}/sys/kernel/random/uuid r,
        @{PROC}/sys/kernel/shmmax r,
        @{PROC}/sys/kernel/yama/ptrace_scope r,
        @{PROC}/uptime r,
        @{PROC}/version r,
        @{PROC}/version_signature r,
  owner @{PROC}/@{pid}/cgroup r,
  owner @{PROC}/@{pid}/clear_refs w,
  owner @{PROC}/@{pid}/cmdline rk,
  owner @{PROC}/@{pid}/comm rk,
  owner @{PROC}/@{pid}/environ r,
  owner @{PROC}/@{pid}/fd/ r,
  owner @{PROC}/@{pid}/fdinfo/@{int} r,
  owner @{PROC}/@{pid}/limits r,
  owner @{PROC}/@{pid}/loginuid r,
  owner @{PROC}/@{pid}/sessionid r,
  owner @{PROC}/@{pid}/smaps_rollup r,
  owner @{PROC}/@{pid}/task/ r,
  owner @{PROC}/@{pid}/task/@{tid}/smaps r,
  owner @{PROC}/@{pid}/task/@{tid}/stat r,
  owner @{PROC}/@{pid}/task/@{tid}/statm r,

  # Allow setting up pseudoterminal via /dev/pts system. This is safe because
  # the flatpak uses a per-app devpts.
  /dev/ptmx rw,

  include if exists <abstractions/app/flatpak.d>

# vim:syntax=apparmor
