github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap-confine/README.mount_namespace (about) 1 = Mount namespace setup in snap-confine = 2 3 This document provides a terse explanation of the mount setup using syscall 4 traces to show precisely what is happening and show the difference between 5 all snaps images and classic. 6 7 Obtain traces with (ignoring select helps keep strace from hanging): 8 $ sudo snap install hello-world 9 $ sudo /usr/lib/snapd/snap-discard-ns hello-world 10 $ sudo strace -f -vv -s8192 -o /tmp/trace.unshare -e trace='!select' /snap/bin/hello-world 11 $ sudo strace -f -vv -s8192 -o /tmp/trace.setns -e trace='!select' /snap/bin/hello-world 12 13 Examine /tmp/trace.unshare for initial mount namespace setup and 14 /tmp/trace.setns for seeing how the mount namespace is reused on subsequent 15 runs. Note that running /usr/lib/snapd/snap-discard-ns prior to running the 16 command is required for creating the new mount namespace (otherwise the 17 previous mount namespace will be reused). 18 19 20 = Mount namespace setup in detail = 21 Here are the steps snap-confine takes when setting up the mount namespace for a 22 given snap: 23 24 # Create the /run/snapd/ns directory to save off the mount namespace to be 25 # shared on other app-invocations 26 open("/", O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC) = 3 27 mkdirat(3, "run", 0755) = -1 EEXIST (File exists) 28 openat(3, "run", O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC) = 4 29 mkdirat(4, "snapd", 0755) = -1 EEXIST (File exists) 30 openat(4, "snapd", O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC) = 3 31 mkdirat(3, "ns", 0755) = -1 EEXIST (File exists) 32 openat(3, "ns", O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC) = 4 33 34 # If /run/snapd/ns/<snap name>.mnt exists, enter that namespace: 35 openat(3, "hello-world.mnt", O_RDONLY|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0600) = 5 36 fstatfs(5, {f_type=0x6e736673, ...) = 0 37 setns(5, CLONE_NEWNS) = 0 38 ... mount namespace setup finished, go on to setup the rest of the sandbox ... 39 40 41 # Otherwise, create a new mount namespace 42 unshare(CLONE_NEWNS) 43 mount("none", "/", NULL, MS_REC|MS_SLAVE, NULL) = 0 44 45 # Classic-only - mount rootfs in the namespace 46 mkdir("/tmp/snap.rootfs_HkQghZ", 0700) = 0 47 mount("/snap/ubuntu-core/current", "/tmp/snap.rootfs_HkQghZ", NULL, MS_BIND, NULL) = 0 48 49 # Classic only - mount directories from host over rootfs 50 mount("/dev", "/tmp/snap.rootfs_HkQghZ/dev", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 51 mount("/etc", "/tmp/snap.rootfs_HkQghZ/etc", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 52 mount("/home", "/tmp/snap.rootfs_HkQghZ/home", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 53 mount("/root", "/tmp/snap.rootfs_HkQghZ/root", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 54 mount("/proc", "/tmp/snap.rootfs_HkQghZ/proc", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 55 mount("/sys", "/tmp/snap.rootfs_HkQghZ/sys", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 56 mount("/tmp", "/tmp/snap.rootfs_HkQghZ/tmp", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 57 mount("/var/snap", "/tmp/snap.rootfs_HkQghZ/var/snap", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 58 mount("/var/lib/snapd", "/tmp/snap.rootfs_HkQghZ/var/lib/snapd", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 59 mount("/var/tmp", "/tmp/snap.rootfs_HkQghZ/var/tmp", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 60 mount("/run", "/tmp/snap.rootfs_HkQghZ/run", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 61 mount("/media", "/tmp/snap.rootfs_HkQghZ/media", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 62 mount("/lib/modules", "/tmp/snap.rootfs_HkQghZ/lib/modules", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 63 mount("/usr/src", "/tmp/snap.rootfs_HkQghZ/usr/src", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 64 mount("/var/log", "/tmp/snap.rootfs_HkQghZ/var/log", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 65 mount("/snap", "/tmp/snap.rootfs_HkQghZ/snap", NULL, MS_BIND|MS_REC|MS_SLAVE, NULL) = 0 66 mount("/snap/ubuntu-core/current/etc/alternatives", "/tmp/snap.rootfs_HkQghZ/etc/alternatives", NULL, MS_BIND|MS_SLAVE, NULL) = 0 67 mount("/", "/tmp/snap.rootfs_HkQghZ/var/lib/snapd/hostfs", NULL, MS_RDONLY|MS_BIND, NULL) = 0 68 69 # Classic only - pivot_root into the rootfs 70 pivot_root(".", ".") = 0 71 umount2(".", MNT_DETACH) = 0 72 73 # Create a bind-mounted private /tmp 74 mkdir("/tmp/snap.0_snap.hello-world.hello-world_QXGSt1", 0700) = 0 75 mkdir("/tmp/snap.0_snap.hello-world.hello-world_QXGSt1/tmp", 01777) = 0 76 mount("/tmp/snap.0_snap.hello-world.hello-world_QXGSt1/tmp", "/tmp", NULL, MS_BIND, NULL) = 0 77 mount("none", "/tmp", NULL, MS_PRIVATE, NULL) = 0 78 79 # Create a per-snap /dev/pts 80 mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance,ptmxmode=0666,mode=0"...) 81 mount("/dev/pts/ptmx", "/dev/ptmx", 0x5574dfe9a5c3, MS_BIND, NULL) 82 83 # Process snap-defined mounts (eg, for content interface, mount the source to 84 # the target as defined in /var/lib/snapd/mount/snap.<name>.<command>.fstab) 85 # Eg: 86 mount("/snap/some-content-snap/current/src", "/snap/hello-world/current/dst", NULL, MS_RDONLY|MS_NOSUID|MS_NODEV|MS_BIND, NULL) 87 88 # Bind mount this namespace to the application-specific NSFS magic file to 89 # preserve it across snap invocations (an fchdir() happened just after the 90 # unshare(), above). 91 mount("/proc/12887/ns/mnt", "hello-world.mnt", NULL, MS_BIND, NULL) = 0 92 ... mount namespace setup finished, go on to setup the rest of the sandbox ...