Proposal: Add /dev/shm namespace to all snaps by default


#1

Currently we have very strict rules on the names of files a snap may create in /dev/shm. This generally means that applications either need to have a special case carved out such as in the browser-support interface, or need to be rewritten to accommodate the strict naming requirements.

  • For closed-source applications where the packager is not upstream, rewriting the application is impossible.
  • For closed-source applications where the packager is the upstream, rewriting the application is difficult to impossible or undesirable.
  • For open-source applications this likely means carrying a delta unless upstream are willing to include and maintain a snap-specific patch in their source tree.

As the intention of snaps is to allow applications to work with no modifications, then I propose that snapd implements a new namespace for each snap so that they have their own /dev/shm directory similar to how we namespace /tmp (probably a different mechanism though).

Moby, the upstream of the Docker product does /dev/shm namespacing so this is definitely possible to achieve.

Snaps should then be able to opt-into importing subsets of the /dev/shm from the system, or exporting parts of their namespaced /dev/shm back to the system, and other snaps may consume the exports from one snap directly or from the host system’s /dev/shm. This will require a new plug and slot pair to provide both sides, the export and the import, for snaps to define subsets for exporting and importing.

plugs:
  shared-memory:
    interface: shm
    name: shared-memory-export
    paths:
    - PostgreSQL.* # import any shared memory file matching `/dev/shm/PostgreSQL.*` from the host
    - pulse-shm-* # import pulse shared memory from the host

slots:
  shared-memory:
    interface: shm
    name: shared-memory-import
    paths:
    - com.google.Chrome.* # export standard google chrome shared memory thingy
    - .com.google.Chrome.* # export a hidden variant of above
    - org.chromium.* # chromium variant of above
    - .org.chromium.* # hidden chromium variant
    - .io.nwjs.* # nwjs

apps:
  some-app:
    plugs:
    - shared-memory

Once namespaced /dev/shm support is implemented in snapd we will be able to allow browsers to not need the transitional interface browser-support and proprietary applications will be able to make whatever names they desire. Only when they export or import do we need to worry about naming. If the exports and imports are purely for the snap world then we can rename them as we need to prevent one snap trampling on another by both exporting the same names - the idea is that when we export from a snap then .io.nwjs.foo becomes snap.snapname.io.nwjs.foo on the host, but .io.nwjs.foo when used inside another snap.

For the purposes of completion the apparmor rule should allow permissions of mrw, on the shared memory exported and imported. These interfaces should not be automatically connected, and require a manual review.

Thoughts?


#2

For others, the current direction is specified here: Shared memory in /dev/shm rewriting

A per-snap /dev/shm is an interesting idea, but I’m not sure that it will solve all cases (that would have to be investigated). Eg, suppose we bind mount /dev/shm/snap.snapname from the host onto /dev/shm in the guest, what happens with the problematic sem_open()?

Assuming that can be addressed, I suspect that simply the act of having a per-snap /dev/shm without the importing/exporting will solve many problems-- AIUI, it would be fairly unusual for an application to expose endpoints in /dev/shm for other unrelated applications to use (please correct me if I’m wrong). Therefore, simply making it per-snap is probably sufficient.


#3

That is my understanding too. I added the import and export as an idea in case anybody can think of an application that needs it, so I could win the “just in case” Bonus Internet Points :tm: - we can drop that part of the proposal for now and think about just isolating /dev/shm per-snap until someone hits on a scenario where they really need the import/export to function at which point they can come back here and tell us their scenario.


#4

This discussion seems to have disappeared off the radar. Any more thoughts from anyone, or a commitment to try it out?


#5

@jdstrand / @daniel – If I may ask: What’s the current status of /dev/shm access for confined snaps? I’ve read this topic as well as Shared memory in /dev/shm rewriting and saw the app armor exceptions for FF/Chrome in this commit by jdstrand.

Background: I’ve built a snap for WPE Webkit intended as a kiosk browser on mir-kiosk. All works fine if I use snapcraft-preload + a desktop-launcher, but that slows down startup considerably from ~1s to about 10s. Without preload/launch, logs indicate that WPE can’t access /dev/shm and thus fails to run properly (e.g. can’t find libraries and is just overall unpredictable). I’m rather new to this, so maybe its my fault for missing something obvious, but I was wondering if there’s maybe just a tiny issue I’m oblivious to.

Log message without snapcraft-preload + desktop-launch:

2019-05-15T12:20:18Z wpe-webkit-mir-kiosk.browser[27748]: Failed to create shared memory file /WK2SharedMemory.3252455929: Permission denied

#6

Note that WK2SharedMemory is allowed with ‘browser-support’ when specifying ‘allow-sandbox: true’, but this is not allowed to non-major browser vendors.

Also note that it is desktop-launch that is likely causing the slowdown, not snapcraft-preload. Also, desktop-launch probably is only slow on the first launch after installing/refreshing to a new revision. If you can get your snap to work without desktop-launch, perhaps try with just snapcraft-preload. I don’t know if you are building webkit from source as well, but if you are, you could also patch it to by sandbox-compliant.