Shared memory in /dev/shm rewriting

I’m attempting to snap a popular game/app which has been a devil. Unfortunately it makes heavy use of Shared Memory using /dev/shm files. I’ve attempted using the snapcraft-preload to automatically rewrite the paths but it seems that the nested style of execution that the app performs kills-off the environment where LD_PRELOAD is defined before the client starts. We really need a way for the shared memory file paths to be transparently re-named without both the applications knowing about it (makemkv seems to ignore that the filename changed and detects that the file wasn’t created where it wanted it and b0rks, for example) and that does not rely on LD_PRELOAD due to the ephemeral nature of environment variables and apps being able to unset when they execve a child process.

Thoughts?

1 Like

By Popular Game/app you mean steam right? Though i won’t be able to run :frowning: arch linux user

Our game also using shared memory for client-server communication on initialization. Trying to create working snap package for it and can’t get it working so far and shared memory is one of issues.

I’m also testing the snapcraft-preload part for the firefox snap, for the same reason (firefox tries to write shared memory to /dev/shm/org.chromium.XXXXXX, it uses code from chromium for IPC).
The shim doesn’t seem to have any effect, maybe because firefox launches subprocesses with a “clean” environment, and thus wipes the value of LD_PRELOAD.

I’m also interested in thoughts and suggestions.

doesnt it do that via a wrapper script ? (did you try to patch that ?)

I haven’t tried, and haven’t actually confirmed that this is really what’s happening. Just guessing there. But even if it did, the point of having a preload part is to not have to patch the upstream code, and in the case of firefox it’s even more important as the snap is basically built out of an existing binary build, it’s not being recompiled just for the snap.

In the particular case of firefox, it is expected to use the transitional browser-support interface, and that interface can be updated for firefox’s use of /dev/shm.

There are two straightforward routes to solving the shared memory issue:

The first one is to prefix the shared memory files snap.<snap name>. This works out of the box without any interfaces.

Here are the specific apparmor rules:

# App-specific access to files and directories in /dev/shm. We allow file
# access in /dev/shm for shm_open() and files in subdirectories for open()
/{dev,run}/shm/snap.@{SNAP_NAME}.** mrwlkix,
# Also allow app-specific access for sem_open()
/{dev,run}/shm/sem.snap.@{SNAP_NAME}.* mrwk,

Then, if the above doesn’t work for you and your application, game, etc needs custom rules along the line of what we have for chromium, we can define a new interface for that. Just let us know about the details and we’ll implement the interface and release on the upcoming snapd.

1 Like

Excellent! I’ve prepared a pull request that adds that exception: Add an exception for Firefox's access to /dev/shm, by oSoMoN · Pull Request #4005 · canonical/snapd · GitHub.

2 Likes

I’ve run into this issue with a python3/Gtk3 app I’m working on (my first snap). I have a large gap in my apparmor knowledge (I know next to nothing about it), so could you clarify where the apparmor rules should be placed/edited/etc? Or have I misunderstood something here (very likely)? Thanks.

EDIT: I now realize that using snapcraft-preload is supposed to change the /dev/shm/ path to be snap-specific (nothing needs to be done in relation to apparmor). However, it’s not clear to me if I can use “snapcraft-preload desktop-launch binary”, or …? I’ll have to work more on this later.

Chaining snapcraft-preload and desktop-launch works fine. In both cases they just set environment variables and then exec the next command on the command-line.

The actual code looks something like this:

#!/bin/bash

export MY_SUPER_ENVIRONMENT=awesome

# chain to the next command - $@ has the commandline without our current filename ($0)
exec "$@"

Do they set some of the same environment variables? I get different results with “command: snapcraft-preload desktop-launch $SNAP/bin/app” than I do with “command: desktop-launch snapcraft-preload $SNAP/bin/app”

Output with “command: snapcraft-preload desktop-launch $SNAP/bin/app”:

mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.cache/gio-modules’ is not a directory Unable to open directory /home/dev/snap/disk-copy-utility/x18/.cache/gio-modules: Error opening directory ‘/home/dev/snap/disk-copy-utility/x18/.cache/gio-modules’: No such file or directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/glib-2.0/schemas’ is not a directory ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/glib-2.0/schemas’ is not a directory ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/glib-2.0/schemas’ is not a directory ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/glib-2.0/schemas’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Adwaita’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/DMZ-Black’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/DMZ-White’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Humanity’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Humanity-Dark’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/LoginIcons’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/hicolor’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/ubuntu-mono-dark’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/ubuntu-mono-light’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Adwaita’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/DMZ-Black’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/DMZ-White’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Humanity’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/Humanity-Dark’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/LoginIcons’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/hicolor’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/ubuntu-mono-dark’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.local/share/icons/ubuntu-mono-light’ is not a directory mkdir: cannot create directory ‘/home/dev/snap/disk-copy-utility’: Read-only file system ln: target ‘/home/dev/snap/disk-copy-utility/x18/.cache/immodules’ is not a directory /snap/disk-copy-utility/x18/bin/desktop-launch: line 356: /home/dev/snap/disk-copy-utility/x18/.cache/immodules/immodules.cache: No such file or directory (app:18664): GLib-GIO-ERROR **: No GSettings schemas are installed on the system Trace/breakpoint trap (core dumped)

command: desktop-launch snapcraft-preload $SNAP/bin/app

(app:19163): GLib-GIO-WARNING **: Error creating IO channel for /proc/mounts: Permission denied (g-file-error-quark, 2) Traceback (most recent call last): File “/snap/disk-copy-utility/x19/bin/app”, line 11, in load_entry_point(‘disk-copy-utility==0.1’, ‘console_scripts’, ‘app’)() File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/pkg_resources/init.py”, line 572, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/pkg_resources/init.py”, line 2752, in load_entry_point return ep.load() File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/pkg_resources/init.py”, line 2405, in load return self.resolve() File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/pkg_resources/init.py”, line 2411, in resolve module = import(self.module_name, fromlist=[‘name’], level=0) File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/disk_copy_utility/app.py”, line 155, in builder.connect_signals(MainApp()) File “/snap/disk-copy-utility/x19/lib/python3.5/site-packages/disk_copy_utility/app.py”, line 20, in init self.q = Queue() File “/snap/disk-copy-utility/x19/usr/lib/python3.5/multiprocessing/context.py”, line 101, in Queue return Queue(maxsize, ctx=self.get_context()) File “/snap/disk-copy-utility/x19/usr/lib/python3.5/multiprocessing/queues.py”, line 42, in init self._rlock = ctx.Lock() File “/snap/disk-copy-utility/x19/usr/lib/python3.5/multiprocessing/context.py”, line 66, in Lock return Lock(ctx=self.get_context()) File “/snap/disk-copy-utility/x19/usr/lib/python3.5/multiprocessing/synchronize.py”, line 163, in init SemLock.init(self, SEMAPHORE, 1, 1, ctx=ctx) File “/snap/disk-copy-utility/x19/usr/lib/python3.5/multiprocessing/synchronize.py”, line 60, in init unlink_now) PermissionError: [Errno 13] Permission denied

I assume the first option (snapcraft-preload then desktop-launch) is “progress”, since otherwise I seem to get the same issue as before with the second option (desktop-launch then snapcraft-preload).

Ok, yes, I forgot that the desktop-launch will get intercepted by the snapcraft-preload, so desktop-launch should be before snapcraft-preload in the chain.

As to the error, you’re receiving a permission denied trying to access /proc/mounts which can be fixed by plugging mount-observe and manually connecting it with sudo snap connect your-snap:mount-observe. Could you raise further issues in a separate topic please, as this topic is related to /dev/shm and discussing tangentially will confuse other readers of our conversation.