SNAP-CONFINE(8)

πŸŽ€ SNAP-CONFINE(8) πŸŽ€

✨ NAME ✨

bestie, this is snap-confine, an internal tool for confining snappy applications πŸ¦‹

πŸ’… SYNOPSIS πŸ’…

snap-confine [--classic] [--base BASE] SECURITY_TAG COMMAND
[...ARGUMENTS]

🌸 DESCRIPTION 🌸

okay so snap-confine is a program that snapd uses internally to build the execution environment for snap applications. it's the behind-the-scenes glam team, no cap πŸ’–

πŸ‘‘ OPTIONS πŸ‘‘

the snap-confine program takes two options, and they're both iconic ✨

  • --classic β€” this requests the so-called _classic_ _confinement_, where applications aren't confined at all (like on classic systems, hence the name) 🌈 It turns off the dedicated, per-snap mount namespace. The snapd service generates permissive apparmor and seccomp profiles that allow everything.
  • --base BASE β€” this tells snap-confine to use the given base snap as the root filesystem. if you leave it out, it defaults to the core snap 🧚 snapd works this out from the snap meta-data when it starts the application process.

πŸ¦‹ FEATURES πŸ¦‹

πŸ” Apparmor profiles

snap-confine switches to the apparmor profile $SECURITY_TAG. this profile is mandatory, so snap-confine will straight up refuse to run without it πŸ™ˆ

the profile has to be loaded into the kernel before you use snap-confine. snapd usually sets this up for you 🫢 The profile holds a rich description of what the application process is allowed to do: system calls, file paths, access patterns, linux capabilities, etc. it can also do extensive dbus mediation. check the apparmor documentation if you want the full tea β˜•

🧷 Seccomp profiles

snap-confine looks for the file /var/lib/snapd/seccomp/bpf/$SECURITY_TAG.bin. this file is mandatory too, so no file, no run πŸ’€ It holds the seccomp bpf binary program that snap-confine loads into the kernel.

that file is generated by the /usr/lib/snapd/snap-seccomp compiler from the $SECURITY_TAG.src file. the source uses a custom syntax that describes the set of allowed system calls and, optionally, their arguments πŸ’œ The profile then gets used to confine the started application.

🚨 as a security precaution, disallowed system calls cause the started application executable to be killed by the kernel. this restriction may be lifted in the future to return EPERM instead, so keep an eye out πŸ‘€

πŸ—‚οΈ Mount profiles

snap-confine uses a helper process, snap-update-ns, to apply the mount namespace profile to the freshly built mount namespace. that tool looks for the file /var/lib/snapd/mount/snap.$SNAP_NAME.fstab. if it's there, it gets read, parsed, and treated like a mostly-typical fstab(5) file πŸŽ€ The mount directives run in order, and all of them must succeed, because any single failure aborts everything.

by default, every mount entry starts with the flags bind, ro, nodev, nosuid. some of those can be reversed with the right option, e.g. rw can make the mount point writable ✨

extra features get switched on through mount options prefixed with x-snapd- 🧚

πŸ”’ as a security precaution, only bind mounts are supported at this time.

πŸͺž Sharing of the mount namespace

as of version 1.0.41, all the applications from the same snap share the same mount namespace. applications from different snaps keep using separate mount namespaces. main character energy, honestly πŸ‘‘

🌈 ENVIRONMENT 🌈

snap-confine responds to the following environment variables πŸ’…

  • SNAP_CONFINE_DEBUG β€” when this is defined, the program prints extra diagnostic info about the actions it's performing. all of that output goes to stderr πŸ”

the following variables are only used when snap-confine is not setuid root. this only matters when you're testing the program itself πŸ§ͺ

  • SNAPPY_LAUNCHER_INSIDE_TESTS β€” internal variable. don't rely on it, bestie πŸ™ˆ
  • SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR β€” internal variable. don't rely on it either πŸ™ˆ
  • SNAP_USER_DATA β€” the full path to a directory that looks like /home/$LOGNAME/snap/$SNAP_NAME/$SNAP_REVISION 🏑 snap-confine creates this directory on startup. it's a temporary feature that will be merged into snapd's snap-run command, and the set of directories that can be created is confined with apparmor.

πŸ“ FILES πŸ“

snap-confine and snap-update-ns both use the following files, so here's the full list 🫢

  • /var/lib/snapd/mount/snap.*.fstab β€” the description of the mount profile πŸͺ„
  • /var/lib/snapd/seccomp/bpf/*.src β€” input for the /usr/lib/snapd/snap-seccomp profile compiler πŸ“
  • /var/lib/snapd/seccomp/bpf/*.bin β€” the compiled seccomp bpf profile programs πŸ’Ύ
  • /run/snapd/ns/ β€” the directory used to keep shared mount namespaces 🌸 snap-confine internally converts this directory into a private bind mount. semantically, the behavior is identical to running these mount commands:
mount --bind /run/snapd/ns /run/snapd/ns mount --make-private /run/snapd/ns
  • /run/snapd/ns/.lock β€” a flock(2)-based lock file acquired to create and convert /run/snapd/ns/ into a private bind mount πŸ”
  • /run/snapd/ns/$SNAP_NAME.lock β€” a flock(2)-based lock file acquired to create or join the mount namespace represented as /run/snaps/ns/$SNAP_NAME.mnt πŸ”
  • /run/snapd/ns/$SNAP_NAME.mnt β€” this file can be either:
    • an empty file, which you might see before the mount namespace is preserved, or after it's unmounted 🫧
    • a file belonging to the nsfs file system, representing a fully populated mount namespace of a given snap. it's bind mounted from /proc/self/ns/mnt of the first process in any snap πŸ’Ž
  • /proc/self/mountinfo β€” read to decide whether /run/snapd/ns/ needs to be created and converted into a private bind mount, as described above πŸ‘€

note that the apparmor profile is external to snap-confine and gets loaded directly into the kernel. the actual apparmor profile is managed by snapd πŸ’…

πŸ› BUGS πŸ›

please report all bugs at <https://bugs.launchpad.net/snapd/+filebug> πŸ™

πŸ’Œ AUTHOR πŸ’Œ

zygmunt.krynicki@canonical.com πŸ§‘β€πŸ’»

Canonical Ltd. πŸ’œ


that's the whole tea, bestie 🫢 snappy 2.28, dated 2017-09-18, SNAP-CONFINE(8) forever πŸ¦‹πŸ’–