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

# GNOME JavaScript interpreter. It is used to run some gnome internal app
# as well as third party extensions.
#
# Therefore, by default, some extension are confined under this profile. To fix
# this, the various programs using gjs must never run gjs as module, they need
# to run it as executable with a specific script.
#
# This currently concerns:
#
# - gnome-extension-ding (used to not be started as a module)
# - org.gnome.ScreenSaver (simple dbus service)
# - org.gnome.Shell.Extensions (full UI app, requires gnome-strict, graphics, ...)
# - org.gnome.Shell.Notifications (simple dbus service)
# - org.gnome.Shell.Screencast (simple dbus service)

abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{bin}/gjs-console
@{att} = /att/gjs/
profile gjs /{,usr/}bin/gjs-console flags=(attach_disconnected,attach_disconnected.path=@{att}) {
  include <abstractions/attached/base>
  include <abstractions/bus/session/org.gnome.Shell.Introspect>
  include <abstractions/attached/consoles>
  include <abstractions/dconf-write>
  include <abstractions/fontconfig-cache-read>

  # Only needed by org.gnome.Shell.Extensions
  include <abstractions/camera>
  include <abstractions/gnome-strict>
  include <abstractions/graphics>
  include <abstractions/gstreamer>
  include <abstractions/attached/nameservice-strict>

  # Only needed by gnome-extension-ding
  include <abstractions/bus/session/org.freedesktop.FileManager1>
  include <abstractions/bus/session/org.gnome.ArchiveManager1>
  include <abstractions/bus/session/org.gnome.Nautilus.FileOperations2>
  include <abstractions/bus/session/org.gtk.Private.RemoteVolumeMonitor>
  include <abstractions/bus/session/org.gtk.vfs.Daemon>
  include <abstractions/bus/session/org.gtk.vfs.Metadata>
  include <abstractions/bus/system/net.hadess.SwitcherooControl>

  network netlink raw,

  unix type=stream peer=(label=gnome-shell),

  signal receive set=(term hup) peer=gdm,

  include <abstractions/bus/session/own>

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

  dbus (send receive) bus=session path=/com/rastersoft/dingextension{,/**}
       interface=com.rastersoft.dingextension{,.*}
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus (send receive) bus=session path=/com/rastersoft/dingextension{,/**}
       interface=org.gtk.Actions
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus (send receive) bus=session path=/com/rastersoft/dingextension{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus send bus=session path=/com/rastersoft/dingextension{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus send bus=session path=/com/rastersoft/dingextension{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},com.rastersoft.dingextension{,.*}}", label=gnome-shell),
  dbus send bus=session path=/org/freedesktop/DBus
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"),
  dbus send bus=session path=/org/freedesktop/DBus
       interface=org.freedesktop.DBus*
       peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"),
  dbus send bus=system path=/org/freedesktop/DBus
       interface=org.freedesktop.DBus*
       peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"),

  include <abstractions/bus/session/own>

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

  unix type=stream peer=(label=gnome-shell),

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

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

  # Only needed by org.gnome.ScreenSaver
  include <abstractions/bus/session/own>

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

  # Only needed by org.gnome.Shell.Extensions
  include <abstractions/bus/session/own>

  dbus bind bus=session name=org.gnome.Shell.Extensions{,.*},
  dbus receive bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.gnome.Shell.Extensions{,.*}
       peer=(name="@{busname}"),
  dbus send bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.gnome.Shell.Extensions{,.*}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus (send receive) bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus send bus=session path=/org/gnome/Shell/Extensions{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.DBus}"),

  # Only needed by org.gnome.Shell.Notifications
  include <abstractions/bus/session/own>

  dbus bind bus=session name=org.gnome.Shell.Notifications{,.*},
  dbus receive bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.gnome.Shell.Notifications{,.*}
       peer=(name="@{busname}"),
  dbus send bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.gnome.Shell.Notifications{,.*}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus (send receive) bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus send bus=session path=/org/gnome/Shell/Notifications{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.DBus}"),

  # Only needed by org.gnome.Shell.Screencast
  include <abstractions/bus/session/own>

  dbus bind bus=session name=org.gnome.Shell.Screencast{,.*},
  dbus receive bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.gnome.Shell.Screencast{,.*}
       peer=(name="@{busname}"),
  dbus send bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.gnome.Shell.Screencast{,.*}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus (send receive) bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.freedesktop.DBus.Properties
       member={Get,GetAll,Set,PropertiesChanged}
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.freedesktop.DBus.Introspectable
       member=Introspect
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus receive bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member=GetManagedObjects
       peer=(name="{@{busname},org.freedesktop.DBus}"),
  dbus send bus=session path=/org/gnome/Shell/Screencast{,/**}
       interface=org.freedesktop.DBus.ObjectManager
       member={InterfacesAdded,InterfacesRemoved}
       peer=(name="{@{busname},org.freedesktop.DBus}"),

  @{exec_path} mrix,

  # gnome-extension-ding
  @{sh_path}                  rix,
  @{bin}/env                  rix,
  @{bin}/true                 rix,
  @{bin}/gnome-control-center  px,
  @{bin}/nautilus              px,

  /usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} px,
  @{user_share_dirs}/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} px,

  /usr/share/gnome-shell/{,**} r,
  /usr/share/thumbnailers/{,**} r,
  /usr/share/xkeyboard-config-2/{,**} r,

  owner @{desktop_cache_dirs}/nvidia/ w,
  owner @{desktop_cache_dirs}/nvidia/GLCache/ rw,
  owner @{desktop_cache_dirs}/nvidia/GLCache/** rwk,

  owner @{HOME}/ r,

  owner @{user_cache_dirs}/gjs_repl_history rw,
  owner @{user_cache_dirs}/gjs_repl_history-@{int}.tmp rw,

  owner @{user_share_dirs}/gnome-shell/extensions/{,**} r,
  owner @{user_share_dirs}/nautilus/scripts/ r,

  # To register extensions
  owner @{user_config_dirs}/**/NativeMessagingHosts/ r,
  owner @{user_config_dirs}/**/NativeMessagingHosts/org.gnome.shell.extensions.*.json w,
  owner @{user_config_dirs}/**/NativeMessagingHosts/org.gnome.shell.extensions.*.json.@{rand6} rw,
  owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.*.desktop w,
  owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.*.desktop.@{rand6} w,
  owner @{user_share_dirs}/dbus-1/services/ r,
  owner @{user_share_dirs}/dbus-1/services/org.gnome.Shell.Extensions.*.service w,
  owner @{user_share_dirs}/dbus-1/services/org.gnome.Shell.Extensions.*.service.@{rand6} rw,
  owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.*.svg w,
  owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.*.svg.@{rand6} w,
  owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.GSConnect.svg w,
  owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.GSConnect.svg.@{rand6} w,

  owner @{user_desktop_dirs}/ r,
  owner @{user_templates_dirs}/ r,

  owner @{PROC}/@{pid}/mounts r,
  owner @{PROC}/@{pid}/stat r,
  owner @{PROC}/@{pid}/statm r,
  owner @{PROC}/@{pid}/task/ r,
  owner @{PROC}/@{pid}/task/@{tid}/comm rw,
  owner @{PROC}/@{pid}/task/@{tid}/stat r,

  include if exists <local/gjs>
}

# vim:syntax=apparmor
