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 ...