# apparmor.d - Full set of apparmor profiles
# 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}/cockpit-bridge
@{att} = ""
profile cockpit-bridge /{,usr/}bin/cockpit-bridge flags=(complain) {
  include <abstractions/base-strict>
  include <abstractions/bus-session>
  include <abstractions/bus-system>
  include <abstractions/bus/org.freedesktop.NetworkManager>
  include <abstractions/bus/org.freedesktop.timedate1>
  include <abstractions/bus/org.freedesktop.UDisks2>
  include <abstractions/consoles>
  include <abstractions/icons>
  include <abstractions/nameservice-strict>
  include <abstractions/python>

  capability dac_read_search,
  capability net_admin,
  capability sys_nice,
  capability sys_ptrace,

  network inet dgram,
  network inet stream,
  network inet6 dgram,
  network inet6 stream,
  network netlink raw,

  ptrace read,

  signal send set=term peer=cockpit-pcp,
  signal send set=term peer=dbus-daemon,
  signal send set=term peer=journalctl,
  signal send set=term peer=ssh-agent,
  signal send set=term peer=unconfined,
  signal (send receive) set=term peer=cockpit-bridge//sudo,

  unix type=stream addr=none peer=(label=libvirt-dbus, addr=none),

  dbus (send receive) bus=session path=/org/libvirt{,/**}
       interface=org.libvirt{,.*}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus (send receive) bus=session path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus send bus=session path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus send bus=session path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus receive bus=session path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
    unix type=stream addr=none peer=(label=packagekitd, addr=none),

    dbus (send receive) bus=system path=/**
       interface=org.freedesktop.PackageKit{,.*}
       peer=(name="{@{busname},org.freedesktop.PackageKit{,.*}}", label=packagekitd),
    dbus (send receive) bus=system path=/**
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.PackageKit{,.*}}", label=packagekitd),
    dbus send bus=system path=/**
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.PackageKit{,.*}}", label=packagekitd),
    dbus send bus=system path=/**
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.PackageKit{,.*}}", label=packagekitd),
    dbus receive bus=system path=/**
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.PackageKit{,.*}}", label=packagekitd),
  unix type=stream addr=none peer=(label=@{p_systemd}, addr=none),

  dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.systemd1{,.*}
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*}}", label=@{p_systemd}),
  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{,.*}}", label=@{p_systemd}),
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*}}", label=@{p_systemd}),
  dbus send bus=system path=/org/freedesktop/systemd1{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.systemd1{,.*}}", 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{,.*}}", label=@{p_systemd}),
  unix type=stream addr=none peer=(label=libvirt-dbus, addr=none),

  dbus (send receive) bus=system path=/org/libvirt{,/**}
       interface=org.libvirt{,.*}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus (send receive) bus=system path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus send bus=system path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus send bus=system path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),
  dbus receive bus=system path=/org/libvirt{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.libvirt{,.*}}", label=libvirt-dbus),

  @{exec_path} mr,

  @{bin}/cat                  ix,
  @{bin}/date                 ix,
  @{bin}/find                 ix,
  @{bin}/ip                   ix,
  @{python_path}              ix,
  @{bin}/test                 ix,
  @{bin}/file                 ix,

  @{bin}/chage                px,
  @{sbin}/dmidecode           px,
  @{bin}/findmnt              px,
  @{bin}/journalctl           px,
  @{bin}/last                 px,
  @{bin}/lastlog              px,
  @{bin}/lscpu                px,
  @{bin}/passwd               px,
  @{bin}/ssh-agent            px,
  @{bin}/sudo                 cx -> sudo,
  @{bin}/udevadm              cx -> udevadm,
  @{bin}/virsh               rpux,
  @{bin}/virt-install        pux, # TODO: rpx
  @{lib}/cockpit/cockpit-pcp  px,
  @{lib}/cockpit/cockpit-ssh  px,

  # The shell is not confined on purpose.
  @{bin}/@{shells}            ux,

  /usr/{,local/}share/ r,
  /usr/share/cockpit/{,**} r,
  /usr/share/file/** r,
  /usr/share/iproute2/* r,

  @{etc_ro}/login.defs r,
  /etc/cockpit/{,**} r,
  /etc/httpd/conf/mime.types r,
  /etc/machine-id r,
  /etc/mime.types r,
  /etc/motd r,
  /etc/shadow r,
  /etc/shells r,

  / r,
  @{HOME}/ r,

  audit owner @{user_cache_dirs}/ssh-agent.[0-9A-Z]* rw,
  owner @{user_share_dirs}/ r,

  audit @{run}/user/@{uid}/ssh-agent.[0-9A-Z]* rw,
  @{run}/utmp r,

  @{sys}/class/hwmon/ r,
  @{sys}/class/net/ r,
  @{sys}/devices/**/hwmon@{int}/ r,
  @{sys}/devices/**/hwmon@{int}/{name,temp*} r,
  @{sys}/fs/cgroup/ r,
  @{sys}/fs/cgroup/**/ r,
  @{sys}/fs/cgroup/**/cpu.{stat,weight} r,
  @{sys}/fs/cgroup/**/memory* r,
  @{sys}/kernel/kexec_crash_size r,

        @{PROC}/ r,
        @{PROC}/@{pids}/cgroup r,
        @{PROC}/@{pids}/io r,
        @{PROC}/@{pids}/net/dev r,
        @{PROC}/1/cgroup r,
        @{PROC}/cmdline r,
        @{PROC}/diskstats r,
        @{PROC}/loadavg r,
        @{PROC}/uptime r,
  owner @{PROC}/@{pid}/cmdline r,
  owner @{PROC}/@{pid}/fd/ r,
  owner @{PROC}/@{pid}/mounts r,

  /dev/ptmx rw,

  profile sudo flags=(complain) {
    include <abstractions/base-strict>
    include <abstractions/app/sudo>

    signal (send receive) set=(cont hup term) peer=cockpit-bridge,

    @{bin}/cockpit-bridge px,
    @{lib}/cockpit/cockpit-askpass px,

    include if exists <local/cockpit-bridge_sudo>
  }

  profile udevadm flags=(complain) {
    include <abstractions/base-strict>
    include <abstractions/app/udevadm>

    @{run}/udev/data/b@{int}:* r,           # For block devices
    @{run}/udev/data/n@{int} r,             # For network interfaces

    include if exists <local/cockpit-bridge_udevadm>
  }

  include if exists <local/cockpit-bridge>
}

# vim:syntax=apparmor
