File: /var/lib/snapd/apparmor/profiles/snap-update-ns.cups
# Description: Allows snap-update-ns to construct the mount namespace specific
# to a particular snap (see the name below). This specifically includes the
# precise locations of the layout elements.
# vim:syntax=apparmor
#include <tunables/global>
#include if exists "/etc/apparmor.d/tunables/home.d"
profile snap-update-ns.cups (attach_disconnected) {
# The next four rules mirror those above. We want to be able to read
# and map snap-update-ns into memory but it may come from a variety of places.
/usr/lib{,exec,64}/snapd/snap-update-ns mr,
/var/lib/snapd/hostfs/usr/lib{,exec,64}/snapd/snap-update-ns mr,
/{,var/lib/snapd/}snap/{core,snapd}/*/usr/lib/snapd/snap-update-ns mr,
/var/lib/snapd/hostfs/{,var/lib/snapd/}snap/core/*/usr/lib/snapd/snap-update-ns mr,
# Allow reading the dynamic linker cache.
/etc/ld.so.cache r,
# Allow reading, mapping and executing the dynamic linker.
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/{,atomics/}}ld-*.so mrix,
# Allow reading and mapping various parts of the standard library and
# dynamically loaded nss modules and what not.
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/{,atomics/}}libc{,-[0-9]*}.so* mr,
/{,usr/}lib{,32,64,x32}/{,@{multiarch}/{,atomics/}}libpthread{,-[0-9]*}.so* mr,
# Common devices accesses
/dev/null rw,
/dev/full rw,
/dev/zero rw,
/dev/random r,
/dev/urandom r,
# golang runtime variables
/sys/kernel/mm/transparent_hugepage/hpage_pmd_size r,
# glibc 2.27+ may poke this file to find out the number of CPUs
# available in the system when creating a new arena for malloc, see
# Golang issue 25628
/sys/devices/system/cpu/online r,
# Allow reading the command line (snap-update-ns uses it in pre-Go bootstrap code).
owner @{PROC}/@{pid}/cmdline r,
# Allow reading of own maps (Go runtime)
owner @{PROC}/@{pid}/maps r,
# Allow reading file descriptor paths
owner @{PROC}/@{pid}/fd/* r,
# Allow reading /proc/version. For release.go WSL detection.
@{PROC}/version r,
# Allow reading own cgroups
owner @{PROC}/@{pid}/cgroup r,
# Allow reading somaxconn, required in newer distro releases
@{PROC}/sys/net/core/somaxconn r,
# but silence noisy denial of inet/inet6
deny network inet,
deny network inet6,
# Allow reading the os-release file (possibly a symlink to /usr/lib).
/{etc/,usr/lib/}os-release r,
# Allow creating/grabbing global and per-snap lock files.
/run/snapd/lock/cups.lock rwk,
/run/snapd/lock/.lock rwk,
# While the base abstraction has rules for encryptfs encrypted home and
# private directories, it is missing rules for directory read on the toplevel
# directory of the mount (LP: #1848919)
owner @{HOME}/.Private/ r,
owner @{HOMEDIRS}/.ecryptfs/*/.Private/ r,
# Allow reading stored mount namespaces,
/run/snapd/ns/ r,
/run/snapd/ns/cups.mnt r,
# Allow reading per-snap desired mount profiles. Those are written by
# snapd and represent the desired layout and content connections.
/var/lib/snapd/mount/snap.cups.fstab r,
/var/lib/snapd/mount/snap.cups.user-fstab r,
# Allow reading and writing actual per-snap mount profiles. Note that
# the wildcard in the rule to allow an atomic write + rename strategy.
# Those files are written by snap-update-ns and represent the actual
# mount profile at a given moment.
/run/snapd/ns/snap.cups.fstab{,.*} rw,
# NOTE: at this stage the /snap directory is stable as we have called
# pivot_root already.
# Needed to perform mount/unmounts.
capability sys_admin,
# Needed for mimic construction.
capability chown,
# Needed for dropping to calling user when processing per-user mounts
capability setuid,
capability setgid,
# Allow snap-update-ns to override file ownership and permission checks.
# This is required because writable mimics now preserve the permissions
# of the original and hence we may be asked to create a directory when the
# parent is a tmpfs without DAC write access.
capability dac_override,
# Allow freezing and thawing the per-snap cgroup freezers
# v1 hierarchy where we know the group name of all processes of
# a given snap upfront
/sys/fs/cgroup/freezer/snap.cups/freezer.state rw,
# v2 hierarchy, where we need to walk the tree to looking for the tracking
# groups and act on each one
/sys/fs/cgroup/ r,
/sys/fs/cgroup/** r,
/sys/fs/cgroup/**/snap.cups.*.scope/cgroup.freeze rw,
/sys/fs/cgroup/**/snap.cups.*.service/cgroup.freeze rw,
# Allow the content interface to bind fonts from the host filesystem
mount options=(ro bind) /var/lib/snapd/hostfs/usr/share/fonts/ -> /snap/cups/*/**,
mount options=(rw private) -> /snap/cups/*/**,
umount /snap/cups/*/**,
# set up user mount namespace
mount options=(rslave) -> /,
# Allow traversing from the root directory and several well-known places.
# Specific directory permissions are added by snippets below.
/ r,
/etc/ r,
/snap/ r,
/tmp/ r,
/usr/ r,
/var/ r,
/var/lib/ r,
/var/lib/snapd/ r,
/var/snap/ r,
# Allow reading timezone data.
/usr/share/zoneinfo/** r,
# Don't allow anyone to touch /snap/bin
audit deny mount /snap/bin/** -> /**,
audit deny mount /** -> /snap/bin/**,
# Don't allow bind mounts to /media which has special
# sharing and propagates mount events outside of the snap namespace.
audit deny mount -> /media,
# Allow receiving signals from unconfined (eg, systemd)
signal (receive) peer=unconfined,
# Allow sending and receiving signals from ourselves.
signal peer=@{profile_name},
# Commonly needed permissions for writable mimics.
/tmp/ r,
/tmp/.snap/{,**} rw,
# snapd logger.go checks /proc/cmdline
@{PROC}/cmdline r,
# snap checks if vendored apparmor parser should be used at startup
/usr/lib/snapd/info r,
/lib/apparmor/functions r,
# Allow snap-update-ns to open home directory
owner @{HOME}/ r,
# Layout /etc/fonts: bind $SNAP/etc/fonts
mount options=(rbind, rw) "/snap/cups/1112/etc/fonts/" -> "/etc/fonts/",
mount options=(rprivate) -> "/etc/fonts/",
umount "/etc/fonts/",
# Writable mimic /etc
# .. permissions for traversing the prefix that is assumed to exist
"/" r,
# .. variant with mimic at /etc/
# Allow reading the mimic directory, it must exist in the first place.
"/etc/" r,
# Allow setting the read-only directory aside via a bind mount.
"/tmp/.snap/etc/" rw,
mount options=(rbind, rw) "/etc/" -> "/tmp/.snap/etc/",
# Allow mounting tmpfs over the read-only directory.
mount fstype=tmpfs options=(rw) tmpfs -> "/etc/",
# Allow creating empty files and directories for bind mounting things
# to reconstruct the now-writable parent directory.
"/tmp/.snap/etc/*/" rw,
"/etc/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/etc/*/" -> "/etc/*/",
"/tmp/.snap/etc/*" rw,
"/etc/*" rw,
mount options=(bind, rw) "/tmp/.snap/etc/*" -> "/etc/*",
# Allow unmounting the auxiliary directory.
# TODO: use fstype=tmpfs here for more strictness (LP: #1613403)
mount options=(rprivate) -> "/tmp/.snap/etc/",
umount "/tmp/.snap/etc/",
# Allow unmounting the destination directory as well as anything
# inside. This lets us perform the undo plan in case the writable
# mimic fails.
mount options=(rprivate) -> "/etc/",
mount options=(rprivate) -> "/etc/*",
mount options=(rprivate) -> "/etc/*/",
umount "/etc/",
umount "/etc/*",
umount "/etc/*/",
# Writable mimic /snap/cups/1112/etc
"/snap/" r,
"/snap/cups/" r,
# .. variant with mimic at /snap/cups/1112/
"/snap/cups/1112/" r,
"/tmp/.snap/snap/cups/1112/" rw,
mount options=(rbind, rw) "/snap/cups/1112/" -> "/tmp/.snap/snap/cups/1112/",
mount fstype=tmpfs options=(rw) tmpfs -> "/snap/cups/1112/",
"/tmp/.snap/snap/cups/1112/*/" rw,
"/snap/cups/1112/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/snap/cups/1112/*/" -> "/snap/cups/1112/*/",
"/tmp/.snap/snap/cups/1112/*" rw,
"/snap/cups/1112/*" rw,
mount options=(bind, rw) "/tmp/.snap/snap/cups/1112/*" -> "/snap/cups/1112/*",
mount options=(rprivate) -> "/tmp/.snap/snap/cups/1112/",
umount "/tmp/.snap/snap/cups/1112/",
mount options=(rprivate) -> "/snap/cups/1112/",
mount options=(rprivate) -> "/snap/cups/1112/*",
mount options=(rprivate) -> "/snap/cups/1112/*/",
umount "/snap/cups/1112/",
umount "/snap/cups/1112/*",
umount "/snap/cups/1112/*/",
# .. variant with mimic at /snap/cups/1112/etc/
"/snap/cups/1112/etc/" r,
"/tmp/.snap/snap/cups/1112/etc/" rw,
mount options=(rbind, rw) "/snap/cups/1112/etc/" -> "/tmp/.snap/snap/cups/1112/etc/",
mount fstype=tmpfs options=(rw) tmpfs -> "/snap/cups/1112/etc/",
"/tmp/.snap/snap/cups/1112/etc/*/" rw,
"/snap/cups/1112/etc/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/snap/cups/1112/etc/*/" -> "/snap/cups/1112/etc/*/",
"/tmp/.snap/snap/cups/1112/etc/*" rw,
"/snap/cups/1112/etc/*" rw,
mount options=(bind, rw) "/tmp/.snap/snap/cups/1112/etc/*" -> "/snap/cups/1112/etc/*",
mount options=(rprivate) -> "/tmp/.snap/snap/cups/1112/etc/",
umount "/tmp/.snap/snap/cups/1112/etc/",
mount options=(rprivate) -> "/snap/cups/1112/etc/",
mount options=(rprivate) -> "/snap/cups/1112/etc/*",
mount options=(rprivate) -> "/snap/cups/1112/etc/*/",
umount "/snap/cups/1112/etc/",
umount "/snap/cups/1112/etc/*",
umount "/snap/cups/1112/etc/*/",
# Layout /etc/papersize: bind-file $SNAP_COMMON/etc/papersize
mount options=(bind, rw) "/var/snap/cups/common/etc/papersize" -> "/etc/papersize",
mount options=(rprivate) -> "/etc/papersize",
umount "/etc/papersize",
# Writable file /var/snap/cups/common/etc/papersize
"/var/snap/cups/common/etc/papersize" rw,
"/var/snap/cups/common/etc/" rw,
"/var/snap/cups/common/" rw,
"/var/snap/cups/" rw,
# Layout /usr/share/fonts: bind $SNAP/usr/share/fonts
mount options=(rbind, rw) "/snap/cups/1112/usr/share/fonts/" -> "/usr/share/fonts/",
mount options=(rprivate) -> "/usr/share/fonts/",
umount "/usr/share/fonts/",
# Writable mimic /usr/share
# .. variant with mimic at /usr/
"/usr/" r,
"/tmp/.snap/usr/" rw,
mount options=(rbind, rw) "/usr/" -> "/tmp/.snap/usr/",
mount fstype=tmpfs options=(rw) tmpfs -> "/usr/",
"/tmp/.snap/usr/*/" rw,
"/usr/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/usr/*/" -> "/usr/*/",
"/tmp/.snap/usr/*" rw,
"/usr/*" rw,
mount options=(bind, rw) "/tmp/.snap/usr/*" -> "/usr/*",
mount options=(rprivate) -> "/tmp/.snap/usr/",
umount "/tmp/.snap/usr/",
mount options=(rprivate) -> "/usr/",
mount options=(rprivate) -> "/usr/*",
mount options=(rprivate) -> "/usr/*/",
umount "/usr/",
umount "/usr/*",
umount "/usr/*/",
# .. variant with mimic at /usr/share/
"/usr/share/" r,
"/tmp/.snap/usr/share/" rw,
mount options=(rbind, rw) "/usr/share/" -> "/tmp/.snap/usr/share/",
mount fstype=tmpfs options=(rw) tmpfs -> "/usr/share/",
"/tmp/.snap/usr/share/*/" rw,
"/usr/share/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/usr/share/*/" -> "/usr/share/*/",
"/tmp/.snap/usr/share/*" rw,
"/usr/share/*" rw,
mount options=(bind, rw) "/tmp/.snap/usr/share/*" -> "/usr/share/*",
mount options=(rprivate) -> "/tmp/.snap/usr/share/",
umount "/tmp/.snap/usr/share/",
mount options=(rprivate) -> "/usr/share/",
mount options=(rprivate) -> "/usr/share/*",
mount options=(rprivate) -> "/usr/share/*/",
umount "/usr/share/",
umount "/usr/share/*",
umount "/usr/share/*/",
# Writable mimic /snap/cups/1112/usr/share
# .. variant with mimic at /snap/cups/1112/usr/
"/snap/cups/1112/usr/" r,
"/tmp/.snap/snap/cups/1112/usr/" rw,
mount options=(rbind, rw) "/snap/cups/1112/usr/" -> "/tmp/.snap/snap/cups/1112/usr/",
mount fstype=tmpfs options=(rw) tmpfs -> "/snap/cups/1112/usr/",
"/tmp/.snap/snap/cups/1112/usr/*/" rw,
"/snap/cups/1112/usr/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/snap/cups/1112/usr/*/" -> "/snap/cups/1112/usr/*/",
"/tmp/.snap/snap/cups/1112/usr/*" rw,
"/snap/cups/1112/usr/*" rw,
mount options=(bind, rw) "/tmp/.snap/snap/cups/1112/usr/*" -> "/snap/cups/1112/usr/*",
mount options=(rprivate) -> "/tmp/.snap/snap/cups/1112/usr/",
umount "/tmp/.snap/snap/cups/1112/usr/",
mount options=(rprivate) -> "/snap/cups/1112/usr/",
mount options=(rprivate) -> "/snap/cups/1112/usr/*",
mount options=(rprivate) -> "/snap/cups/1112/usr/*/",
umount "/snap/cups/1112/usr/",
umount "/snap/cups/1112/usr/*",
umount "/snap/cups/1112/usr/*/",
# .. variant with mimic at /snap/cups/1112/usr/share/
"/snap/cups/1112/usr/share/" r,
"/tmp/.snap/snap/cups/1112/usr/share/" rw,
mount options=(rbind, rw) "/snap/cups/1112/usr/share/" -> "/tmp/.snap/snap/cups/1112/usr/share/",
mount fstype=tmpfs options=(rw) tmpfs -> "/snap/cups/1112/usr/share/",
"/tmp/.snap/snap/cups/1112/usr/share/*/" rw,
"/snap/cups/1112/usr/share/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/snap/cups/1112/usr/share/*/" -> "/snap/cups/1112/usr/share/*/",
"/tmp/.snap/snap/cups/1112/usr/share/*" rw,
"/snap/cups/1112/usr/share/*" rw,
mount options=(bind, rw) "/tmp/.snap/snap/cups/1112/usr/share/*" -> "/snap/cups/1112/usr/share/*",
mount options=(rprivate) -> "/tmp/.snap/snap/cups/1112/usr/share/",
umount "/tmp/.snap/snap/cups/1112/usr/share/",
mount options=(rprivate) -> "/snap/cups/1112/usr/share/",
mount options=(rprivate) -> "/snap/cups/1112/usr/share/*",
mount options=(rprivate) -> "/snap/cups/1112/usr/share/*/",
umount "/snap/cups/1112/usr/share/",
umount "/snap/cups/1112/usr/share/*",
umount "/snap/cups/1112/usr/share/*/",
# Layout /var/cache/fontconfig: bind $SNAP_DATA/var/cache/fontconfig
mount options=(rbind, rw) "/var/snap/cups/1112/var/cache/fontconfig/" -> "/var/cache/fontconfig/",
mount options=(rprivate) -> "/var/cache/fontconfig/",
umount "/var/cache/fontconfig/",
# Writable mimic /var/cache
# .. variant with mimic at /var/
"/var/" r,
"/tmp/.snap/var/" rw,
mount options=(rbind, rw) "/var/" -> "/tmp/.snap/var/",
mount fstype=tmpfs options=(rw) tmpfs -> "/var/",
"/tmp/.snap/var/*/" rw,
"/var/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/var/*/" -> "/var/*/",
"/tmp/.snap/var/*" rw,
"/var/*" rw,
mount options=(bind, rw) "/tmp/.snap/var/*" -> "/var/*",
mount options=(rprivate) -> "/tmp/.snap/var/",
umount "/tmp/.snap/var/",
mount options=(rprivate) -> "/var/",
mount options=(rprivate) -> "/var/*",
mount options=(rprivate) -> "/var/*/",
umount "/var/",
umount "/var/*",
umount "/var/*/",
# .. variant with mimic at /var/cache/
"/var/cache/" r,
"/tmp/.snap/var/cache/" rw,
mount options=(rbind, rw) "/var/cache/" -> "/tmp/.snap/var/cache/",
mount fstype=tmpfs options=(rw) tmpfs -> "/var/cache/",
"/tmp/.snap/var/cache/*/" rw,
"/var/cache/*/" rw,
mount options=(rbind, rw) "/tmp/.snap/var/cache/*/" -> "/var/cache/*/",
"/tmp/.snap/var/cache/*" rw,
"/var/cache/*" rw,
mount options=(bind, rw) "/tmp/.snap/var/cache/*" -> "/var/cache/*",
mount options=(rprivate) -> "/tmp/.snap/var/cache/",
umount "/tmp/.snap/var/cache/",
mount options=(rprivate) -> "/var/cache/",
mount options=(rprivate) -> "/var/cache/*",
mount options=(rprivate) -> "/var/cache/*/",
umount "/var/cache/",
umount "/var/cache/*",
umount "/var/cache/*/",
# Writable directory /var/snap/cups/1112/var/cache/fontconfig
"/var/snap/cups/1112/var/cache/fontconfig/" rw,
"/var/snap/cups/1112/var/cache/" rw,
"/var/snap/cups/1112/var/" rw,
"/var/snap/cups/1112/" rw,
}