# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2018 Christian Boltz
# Copyright (C) 2021-2026 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{bin}/man
@{att} = /att/man/
profile man /{,usr/}bin/man flags=(attach_disconnected,attach_disconnected.path=@{att}) {
  include <abstractions/attached/base>
  include <abstractions/attached/consoles>
  include <abstractions/shells>

  @{exec_path} mr,

  @{shells_path}     cx -> &man//shell,
  @{browsers_path}   px,
  @{pager_path}      px -> child-pager,
  @{bin}/whatis     rix,

  # Use a special profile when man calls anything groff-related. We only include
  # the programs that actually parse input data in a non-trivial way, not
  # wrappers such as groff and nroff, since they would need a broader profile.
  @{bin}/eqn        rcx -> &man//groff,
  @{bin}/grap       rcx -> &man//groff,
  @{bin}/groff      rcx -> &man//groff,
  @{bin}/grotty     rcx -> &man//groff,
  @{bin}/nroff      rcx -> &man//groff,
  @{bin}/pic        rcx -> &man//groff,
  @{bin}/preconv    rcx -> &man//groff,
  @{bin}/refer      rcx -> &man//groff,
  @{bin}/tbl        rcx -> &man//groff,
  @{bin}/troff      rcx -> &man//groff,
  @{bin}/vgrind     rcx -> &man//groff,

  # Use a special profile when man calls decompressors and other simple filters.
  @{bin}/bzip2      rcx -> filter,
  @{bin}/col        rcx -> filter,
  @{bin}/compress   rcx -> filter,
  @{bin}/gzip       rcx -> filter,
  @{bin}/iconv      rcx -> filter,
  @{bin}/lzip.lzip  rcx -> filter,
  @{bin}/tr         rcx -> filter,
  @{bin}/xz         rcx -> filter,

  /usr/share/groff/{,**} r,
  /usr/{,**/}man/{,**} r,

  @{etc_rw}/man_db.conf r,
  @{etc_rw}/manpath.config r,
  @{etc_rw}/groff/man.local r,

  /var/cache/man/{,**} rw,
  /var/cache/man/{,**/}index.db rwk,

  owner @{user_share_dirs}/man/{,**} rw,
  owner @{user_share_dirs}/man/index.db rwk,

  owner @{tmp}/groff-*-@{rand6} rw,
  owner @{tmp}/groff@{rand6} rw,


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

    include if exists <local/man_shell>
  }

  profile groff {
    include <abstractions/attached/base>
    include <abstractions/attached/consoles>

    @{sh_path}           r,
    @{bin}/eqn        mrix,
    @{bin}/grap       mrix,
    @{bin}/groff      mrix,
    @{bin}/grotty     mrix,
    @{bin}/nroff      mrix,
    @{bin}/pic        mrix,
    @{bin}/preconv    mrix,
    @{bin}/refer      mrix,
    @{bin}/tbl        mrix,
    @{bin}/troff      mrix,
    @{bin}/vgrind     mrix,

    /usr/share/groff/** r,

    /etc/groff/** r,
    /etc/papersize r,

    owner /tmp/groff* rw,
    owner /tmp/* rw,

    include if exists <local/man_groff>
  }

  profile filter {
    include <abstractions/attached/base>
    include <abstractions/attached/consoles>

    signal peer=man,

    @{bin}/bzip2      mr,
    @{bin}/col        mr,
    @{bin}/compress   mr,
    @{bin}/gzip       mr,
    @{bin}/iconv      mr,
    @{bin}/lzip.lzip  mr,
    @{bin}/tr         mr,
    @{bin}/xz         mr,

    /var/cache/man/** w,

    # Manual pages can be more or less anywhere, especially with "man -l", and
    # there's no harm in allowing wide read access here since the worst it can
    # do is feed data to the invoking man process.
          /usr/** r,
    owner @{HOME}/@{XDG_DATA_DIR}/** r,
    owner @{user_projects_dirs}/** r,
    owner @{user_cache_dirs}/** r,
    owner @{MOUNTS}/@{XDG_DATA_DIR}/** r,

    include if exists <local/man_filter>
  }

  include if exists <local/man>
}

# vim:syntax=apparmor
